Index: head/sys/arm/amlogic/aml8726/aml8726_ccm.h =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_ccm.h +++ head/sys/arm/amlogic/aml8726/aml8726_ccm.h @@ -1,320 +0,0 @@ -/*- - * Copyright 2015 John Wehle - * 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 _ARM_AMLOGIC_AML8726_CCM_H -#define _ARM_AMLOGIC_AML8726_CCM_H - -struct aml8726_ccm_gate { - uint32_t addr; - uint32_t bits; -}; - -struct aml8726_ccm_function { - const char *name; - struct aml8726_ccm_gate *gates; -}; - -/* - * aml8726-m3 - */ - -static struct aml8726_ccm_gate aml8726_m3_ethernet[] = { - { 4, 0x00000008 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m3_i2c[] = { - { 0, 0x00000200 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m3_rng[] = { - { 0, 0x00001000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m3_sdio[] = { - { 0, 0x00020000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m3_sdxc[] = { - { 0, 0x00004000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m3_uart_a[] = { - { 0, 0x00002000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m3_uart_b[] = { - { 4, 0x00010000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m3_uart_c[] = { - { 8, 0x00008000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m3_usb_a[] = { - { 4, 0x00200000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m3_usb_b[] = { - { 4, 0x00400000 }, - { 0, 0x00000000 } -}; - -struct aml8726_ccm_function aml8726_m3_ccm[] = { - { "ethernet", aml8726_m3_ethernet }, - { "i2c", aml8726_m3_i2c }, - { "rng", aml8726_m3_rng }, - { "sdio", aml8726_m3_sdio }, - { "sdxc", aml8726_m3_sdxc }, - { "uart-a", aml8726_m3_uart_a }, - { "uart-b", aml8726_m3_uart_b }, - { "uart-c", aml8726_m3_uart_c }, - { "usb-a", aml8726_m3_usb_a }, - { "usb-b", aml8726_m3_usb_b }, - { NULL } -}; - -/* - * aml8726-m6 - */ - -static struct aml8726_ccm_gate aml8726_m6_ethernet[] = { - { 4, 0x00000008 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m6_i2c[] = { - { 0, 0x00000200 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m6_rng[] = { - { 0, 0x00001000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m6_sdio[] = { - { 0, 0x00020000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m6_sdxc[] = { - { 0, 0x00004000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m6_uart_a[] = { - { 0, 0x00002000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m6_uart_b[] = { - { 4, 0x00010000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m6_uart_c[] = { - { 8, 0x00008000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m6_usb_a[] = { - { 4, 0x00200000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m6_usb_b[] = { - { 4, 0x00400000 }, - { 0, 0x00000000 } -}; - -struct aml8726_ccm_function aml8726_m6_ccm[] = { - { "ethernet", aml8726_m6_ethernet }, - { "i2c", aml8726_m6_i2c }, - { "rng", aml8726_m6_rng }, - { "sdio", aml8726_m6_sdio }, - { "sdxc", aml8726_m6_sdxc }, - { "uart-a", aml8726_m6_uart_a }, - { "uart-b", aml8726_m6_uart_b }, - { "uart-c", aml8726_m6_uart_c }, - { "usb-a", aml8726_m6_usb_a }, - { "usb-b", aml8726_m6_usb_b }, - { NULL } -}; - -/* - * aml8726-m8 - */ - -static struct aml8726_ccm_gate aml8726_m8_ethernet[] = { - { 4, 0x00000008 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8_i2c[] = { - { 0, 0x00000200 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8_rng[] = { - { 0, 0x00001000 }, - { 16, 0x00200000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8_sdio[] = { - { 0, 0x00020000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8_sdxc[] = { - { 0, 0x00004000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8_uart_a[] = { - { 0, 0x00002000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8_uart_b[] = { - { 4, 0x00010000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8_uart_c[] = { - { 8, 0x00008000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8_usb_a[] = { - { 4, 0x00200000 }, - { 4, 0x04000000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8_usb_b[] = { - { 4, 0x00400000 }, - { 4, 0x04000000 }, - { 0, 0x00000000 } -}; - -struct aml8726_ccm_function aml8726_m8_ccm[] = { - { "ethernet", aml8726_m8_ethernet }, - { "i2c", aml8726_m8_i2c }, - { "rng", aml8726_m8_rng }, - { "sdio", aml8726_m8_sdio }, - { "sdxc", aml8726_m8_sdxc }, - { "uart-a", aml8726_m8_uart_a }, - { "uart-b", aml8726_m8_uart_b }, - { "uart-c", aml8726_m8_uart_c }, - { "usb-a", aml8726_m8_usb_a }, - { "usb-b", aml8726_m8_usb_b }, - { NULL } -}; - -/* - * aml8726-m8b - */ - -static struct aml8726_ccm_gate aml8726_m8b_ethernet[] = { - { 4, 0x00000008 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8b_i2c[] = { - { 0, 0x00000200 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8b_rng[] = { - { 0, 0x00001000 }, - { 16, 0x00200000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8b_sdio[] = { - { 0, 0x00020000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8b_sdxc[] = { - { 0, 0x00004000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8b_uart_a[] = { - { 0, 0x00002000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8b_uart_b[] = { - { 4, 0x00010000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8b_uart_c[] = { - { 8, 0x00008000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8b_usb_a[] = { - { 4, 0x00200000 }, - { 4, 0x04000000 }, - { 0, 0x00000000 } -}; - -static struct aml8726_ccm_gate aml8726_m8b_usb_b[] = { - { 4, 0x00400000 }, - { 4, 0x04000000 }, - { 0, 0x00000000 } -}; - -struct aml8726_ccm_function aml8726_m8b_ccm[] = { - { "ethernet", aml8726_m8b_ethernet }, - { "i2c", aml8726_m8b_i2c }, - { "rng", aml8726_m8b_rng }, - { "sdio", aml8726_m8b_sdio }, - { "sdxc", aml8726_m8b_sdxc }, - { "uart-a", aml8726_m8b_uart_a }, - { "uart-b", aml8726_m8b_uart_b }, - { "uart-c", aml8726_m8b_uart_c }, - { "usb-a", aml8726_m8b_usb_a }, - { "usb-b", aml8726_m8b_usb_b }, - { NULL } -}; - -#endif /* _ARM_AMLOGIC_AML8726_CCM_H */ Index: head/sys/arm/amlogic/aml8726/aml8726_ccm.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_ccm.c +++ head/sys/arm/amlogic/aml8726/aml8726_ccm.c @@ -1,228 +0,0 @@ -/*- - * Copyright 2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 clock control module driver. - * - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -struct aml8726_ccm_softc { - device_t dev; - struct aml8726_ccm_function *soc; - struct resource *res[1]; - struct mtx mtx; -}; - -static struct resource_spec aml8726_ccm_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, 0 } -}; - -#define AML_CCM_LOCK(sc) mtx_lock(&(sc)->mtx) -#define AML_CCM_UNLOCK(sc) mtx_unlock(&(sc)->mtx) -#define AML_CCM_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "ccm", MTX_DEF) -#define AML_CCM_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) - -static int -aml8726_ccm_configure_gates(struct aml8726_ccm_softc *sc) -{ - struct aml8726_ccm_function *f; - struct aml8726_ccm_gate *g; - char *function_name; - char *functions; - phandle_t node; - ssize_t len; - uint32_t value; - - node = ofw_bus_get_node(sc->dev); - - len = OF_getprop_alloc(node, "functions", - (void **)&functions); - - if (len < 0) { - device_printf(sc->dev, "missing functions attribute in FDT\n"); - return (ENXIO); - } - - function_name = functions; - - while (len) { - for (f = sc->soc; f->name != NULL; f++) - if (strncmp(f->name, function_name, len) == 0) - break; - - if (f->name == NULL) { - /* display message prior to queuing up next string */ - device_printf(sc->dev, - "unknown function attribute %.*s in FDT\n", - len, function_name); - } - - /* queue up next string */ - while (*function_name && len) { - function_name++; - len--; - } - if (len) { - function_name++; - len--; - } - - if (f->name == NULL) - continue; - - AML_CCM_LOCK(sc); - - /* - * Enable the clock gates necessary for the function. - * - * In some cases a clock may be shared across functions - * (meaning don't disable a clock without ensuring that - * it's not required by someone else). - */ - for (g = f->gates; g->bits != 0x00000000; g++) { - value = CSR_READ_4(sc, g->addr); - value |= g->bits; - CSR_WRITE_4(sc, g->addr, value); - } - - AML_CCM_UNLOCK(sc); - } - - OF_prop_free(functions); - - return (0); -} - -static int -aml8726_ccm_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-ccm")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 ccm"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_ccm_attach(device_t dev) -{ - struct aml8726_ccm_softc *sc = device_get_softc(dev); - - sc->dev = dev; - - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M3: - sc->soc = aml8726_m3_ccm; - break; - case AML_SOC_HW_REV_M6: - sc->soc = aml8726_m6_ccm; - break; - case AML_SOC_HW_REV_M8: - sc->soc = aml8726_m8_ccm; - break; - case AML_SOC_HW_REV_M8B: - sc->soc = aml8726_m8b_ccm; - break; - default: - device_printf(dev, "unsupported SoC\n"); - return (ENXIO); - /* NOTREACHED */ - } - - if (bus_alloc_resources(dev, aml8726_ccm_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - AML_CCM_LOCK_INIT(sc); - - return (aml8726_ccm_configure_gates(sc)); -} - -static int -aml8726_ccm_detach(device_t dev) -{ - struct aml8726_ccm_softc *sc = device_get_softc(dev); - - AML_CCM_LOCK_DESTROY(sc); - - bus_release_resources(dev, aml8726_ccm_spec, sc->res); - - return (0); -} - -static device_method_t aml8726_ccm_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_ccm_probe), - DEVMETHOD(device_attach, aml8726_ccm_attach), - DEVMETHOD(device_detach, aml8726_ccm_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_ccm_driver = { - "ccm", - aml8726_ccm_methods, - sizeof(struct aml8726_ccm_softc), -}; - -static devclass_t aml8726_ccm_devclass; - -EARLY_DRIVER_MODULE(ccm, simplebus, aml8726_ccm_driver, - aml8726_ccm_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_LATE); Index: head/sys/arm/amlogic/aml8726/aml8726_clkmsr.h =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_clkmsr.h +++ head/sys/arm/amlogic/aml8726/aml8726_clkmsr.h @@ -1,34 +0,0 @@ -/*- - * Copyright 2014 John Wehle - * 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 _ARM_AMLOGIC_AML8726_CLKMSR_H -#define _ARM_AMLOGIC_AML8726_CLKMSR_H - -int aml8726_clkmsr_bus_frequency(void); - -#endif /* _ARM_AMLOGIC_AML8726_CLKMSR_H */ Index: head/sys/arm/amlogic/aml8726/aml8726_clkmsr.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_clkmsr.c +++ head/sys/arm/amlogic/aml8726/aml8726_clkmsr.c @@ -1,298 +0,0 @@ -/*- - * Copyright 2014-2015 John Wehle - * 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. - * - */ - -/* - * Amlogic aml8726 clock measurement driver. - * - * This allows various clock rates to be determine at runtime. - * The measurements are done once and are not expected to change - * (i.e. FDT fixup provides clk81 as bus-frequency to the MMC - * and UART drivers which use the value when programming the - * hardware). - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -static struct aml8726_clkmsr_clk { - const char * name; - uint32_t mux; -} aml8726_clkmsr_clks[] = { - { "clk81", 7 }, -}; - -#define AML_CLKMSR_CLK81 0 - -#define AML_CLKMSR_NCLKS nitems(aml8726_clkmsr_clks) - -struct aml8726_clkmsr_softc { - device_t dev; - struct resource * res[1]; -}; - -static struct resource_spec aml8726_clkmsr_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, 0 } -}; - -/* - * Duration can range from 1uS to 65535 uS and should be chosen - * based on the expected frequency result so to maximize resolution - * and avoid overflowing the 16 bit result counter. - */ -#define AML_CLKMSR_DURATION 32 - -#define AML_CLKMSR_DUTY_REG 0 -#define AML_CLKMSR_0_REG 4 -#define AML_CLKMSR_0_BUSY (1U << 31) -#define AML_CLKMSR_0_MUX_MASK (0x3f << 20) -#define AML_CLKMSR_0_MUX_SHIFT 20 -#define AML_CLKMSR_0_MUX_EN (1 << 19) -#define AML_CLKMSR_0_MEASURE (1 << 16) -#define AML_CLKMSR_0_DURATION_MASK 0xffff -#define AML_CLKMSR_0_DURATION_SHIFT 0 -#define AML_CLKMSR_1_REG 8 -#define AML_CLKMSR_2_REG 12 -#define AML_CLKMSR_2_RESULT_MASK 0xffff -#define AML_CLKMSR_2_RESULT_SHIFT 0 - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) -#define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ - (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -static int -aml8726_clkmsr_clock_frequency(struct aml8726_clkmsr_softc *sc, unsigned clock) -{ - uint32_t value; - - if (clock >= AML_CLKMSR_NCLKS) - return (0); - - /* - * Locking is not used as this is only expected to be called from - * FDT fixup (which occurs prior to driver initialization) or attach. - */ - - CSR_WRITE_4(sc, AML_CLKMSR_0_REG, 0); - - CSR_BARRIER(sc, AML_CLKMSR_0_REG); - - value = (aml8726_clkmsr_clks[clock].mux << AML_CLKMSR_0_MUX_SHIFT) - | ((AML_CLKMSR_DURATION - 1) << AML_CLKMSR_0_DURATION_SHIFT) - | AML_CLKMSR_0_MUX_EN - | AML_CLKMSR_0_MEASURE; - CSR_WRITE_4(sc, AML_CLKMSR_0_REG, value); - - CSR_BARRIER(sc, AML_CLKMSR_0_REG); - - while ((CSR_READ_4(sc, AML_CLKMSR_0_REG) & AML_CLKMSR_0_BUSY) != 0) - cpu_spinwait(); - - value &= ~AML_CLKMSR_0_MEASURE; - CSR_WRITE_4(sc, AML_CLKMSR_0_REG, value); - - CSR_BARRIER(sc, AML_CLKMSR_0_REG); - - value = (((CSR_READ_4(sc, AML_CLKMSR_2_REG) & AML_CLKMSR_2_RESULT_MASK) - >> AML_CLKMSR_2_RESULT_SHIFT) + AML_CLKMSR_DURATION / 2) / - AML_CLKMSR_DURATION; - - return value; -} - -static void -aml8726_clkmsr_fixup_clk81(struct aml8726_clkmsr_softc *sc, int freq) -{ - pcell_t prop; - ssize_t len; - phandle_t clk_node; - phandle_t node; - - node = ofw_bus_get_node(sc->dev); - - len = OF_getencprop(node, "clocks", &prop, sizeof(prop)); - if ((len / sizeof(prop)) != 1 || prop == 0 || - (clk_node = OF_node_from_xref(prop)) == 0) - return; - - len = OF_getencprop(clk_node, "clock-frequency", &prop, sizeof(prop)); - if ((len / sizeof(prop)) != 1 || prop != 0) - return; - - freq = cpu_to_fdt32(freq); - - OF_setprop(clk_node, "clock-frequency", (void *)&freq, sizeof(freq)); -} - -static int -aml8726_clkmsr_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-clkmsr")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 clkmsr"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_clkmsr_attach(device_t dev) -{ - struct aml8726_clkmsr_softc *sc = device_get_softc(dev); - int freq; - - sc->dev = dev; - - if (bus_alloc_resources(dev, aml8726_clkmsr_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - freq = aml8726_clkmsr_clock_frequency(sc, AML_CLKMSR_CLK81); - device_printf(sc->dev, "bus clock %u MHz\n", freq); - - aml8726_clkmsr_fixup_clk81(sc, freq * 1000000); - - return (0); -} - -static int -aml8726_clkmsr_detach(device_t dev) -{ - struct aml8726_clkmsr_softc *sc = device_get_softc(dev); - - bus_release_resources(dev, aml8726_clkmsr_spec, sc->res); - - return (0); -} - -static device_method_t aml8726_clkmsr_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_clkmsr_probe), - DEVMETHOD(device_attach, aml8726_clkmsr_attach), - DEVMETHOD(device_detach, aml8726_clkmsr_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_clkmsr_driver = { - "clkmsr", - aml8726_clkmsr_methods, - sizeof(struct aml8726_clkmsr_softc), -}; - -static devclass_t aml8726_clkmsr_devclass; - -EARLY_DRIVER_MODULE(clkmsr, simplebus, aml8726_clkmsr_driver, - aml8726_clkmsr_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_EARLY); - -int -aml8726_clkmsr_bus_frequency() -{ - struct resource mem; - struct aml8726_clkmsr_softc sc; - phandle_t node; - u_long pbase, psize; - u_long start, size; - int freq; - - KASSERT(aml8726_soc_hw_rev != AML_SOC_HW_REV_UNKNOWN, - ("aml8726_soc_hw_rev isn't initialized")); - - /* - * Try to access the clkmsr node directly i.e. through /aliases/. - */ - - if ((node = OF_finddevice("clkmsr")) != -1) - if (fdt_is_compatible_strict(node, "amlogic,aml8726-clkmsr")) - goto moveon; - - /* - * Find the node the long way. - */ - if ((node = OF_finddevice("/soc")) == -1) - return (0); - - if ((node = fdt_find_compatible(node, - "amlogic,aml8726-clkmsr", 1)) == 0) - return (0); - -moveon: - if (fdt_get_range(OF_parent(node), 0, &pbase, &psize) != 0 - || fdt_regsize(node, &start, &size) != 0) - return (0); - - start += pbase; - - memset(&mem, 0, sizeof(mem)); - - mem.r_bustag = fdtbus_bs_tag; - - if (bus_space_map(mem.r_bustag, start, size, 0, &mem.r_bushandle) != 0) - return (0); - - /* - * Build an incomplete (however sufficient for the purpose - * of calling aml8726_clkmsr_clock_frequency) softc. - */ - - memset(&sc, 0, sizeof(sc)); - - sc.res[0] = &mem; - - freq = aml8726_clkmsr_clock_frequency(&sc, AML_CLKMSR_CLK81) * 1000000; - - bus_space_unmap(mem.r_bustag, mem.r_bushandle, size); - - return (freq); -} Index: head/sys/arm/amlogic/aml8726/aml8726_fb.h =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_fb.h +++ head/sys/arm/amlogic/aml8726/aml8726_fb.h @@ -1,162 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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 _ARM_AMLOGIC_AML8726_FB_H -#define _ARM_AMLOGIC_AML8726_FB_H - -#define AML_CAV_OSD1_INDEX 0x40 - -#define AML_CAV_LUT_DATAL_REG 0 -#define AML_CAV_LUT_DATAL_WIDTH_MASK (7 << 29) -#define AML_CAV_LUT_DATAL_WIDTH_SHIFT 29 -#define AML_CAV_LUT_DATAL_WIDTH_WIDTH 3 -#define AML_CAV_LUT_DATAL_ADDR_MASK 0x1fffffff -#define AML_CAV_LUT_DATAL_ADDR_SHIFT 0 - -#define AML_CAV_LUT_DATAH_REG 4 -#define AML_CAV_LUT_DATAH_BLKMODE_MASK (3 << 24) -#define AML_CAV_LUT_DATAH_BLKMODE_SHIFT 24 -#define AML_CAV_LUT_DATAH_BLKMODE_LINEAR (0 << 24) -#define AML_CAV_LUT_DATAH_BLKMODE_32x32 (1 << 24) -#define AML_CAV_LUT_DATAH_BLKMODE_64x32 (2 << 24) -#define AML_CAV_LUT_DATAH_WRAP_X (1 << 23) -#define AML_CAV_LUT_DATAH_WRAP_Y (1 << 22) -#define AML_CAV_LUT_DATAH_HEIGHT_MASK (0x1fff << 9) -#define AML_CAV_LUT_DATAH_HEIGHT_SHIFT 9 -#define AML_CAV_LUT_DATAH_WIDTH_MASK 0x1ff -#define AML_CAV_LUT_DATAH_WIDTH_SHIFT 0 - -#define AML_CAV_LUT_ADDR_REG 8 -#define AML_CAV_LUT_ADDR_WR_EN (1 << 9) -#define AML_CAV_LUT_ADDR_RD_EN (1 << 8) -#define AML_CAV_LUT_ADDR_INDEX_MASK 0xff -#define AML_CAV_LUT_ADDR_INDEX_SHIFT 0 - -#define AML_VIU_OSD1_CTRL_REG 64 -#define AML_VIU_OSD_CTRL_OSD_EN (1 << 21) -#define AML_VIU_OSD_CTRL_GLOBAL_ALPHA_MASK (0x1ff << 12) -#define AML_VIU_OSD_CTRL_GLOBAL_ALPHA_SHIFT 12 -#define AML_VIU_OSD_CTRL_OSD_BLK_EN_MASK (0xf << 0) -#define AML_VIU_OSD_CTRL_OSD_BLK_EN_SHIFT 0 - -#define AML_VIU_OSD1_BLK0_CFG_W0_REG 108 -#define AML_VIU_OSD1_BLK1_CFG_W0_REG 124 -#define AML_VIU_OSD1_BLK2_CFG_W0_REG 140 -#define AML_VIU_OSD1_BLK3_CFG_W0_REG 156 -#define AML_VIU_OSD_BLK_CFG_W0_INDEX_MASK (0xff << 16) -#define AML_VIU_OSD_BLK_CFG_W0_INDEX_SHIFT 16 -#define AML_VIU_OSD_BLK_CFG_W0_LITTLE_ENDIAN (1 << 15) -#define AML_VIU_OSD_BLK_CFG_W0_BLKMODE_24 (7 << 8) -#define AML_VIU_OSD_BLK_CFG_W0_RGB_EN (1 << 7) -#define AML_VIU_OSD_BLK_CFG_W0_CMATRIX_RGB (0 << 2) - -#define AML_VIU_OSD1_BLK0_CFG_W1_REG 112 -#define AML_VIU_OSD1_BLK1_CFG_W1_REG 128 -#define AML_VIU_OSD1_BLK2_CFG_W1_REG 144 -#define AML_VIU_OSD1_BLK3_CFG_W1_REG 160 -#define AML_VIU_OSD_BLK_CFG_W1_X_END_MASK (0x1fff << 16) -#define AML_VIU_OSD_BLK_CFG_W1_X_END_SHIFT 16 -#define AML_VIU_OSD_BLK_CFG_W1_X_START_MASK 0x1fff -#define AML_VIU_OSD_BLK_CFG_W1_X_START_SHIFT 0 - -#define AML_VIU_OSD1_BLK0_CFG_W2_REG 116 -#define AML_VIU_OSD1_BLK1_CFG_W2_REG 132 -#define AML_VIU_OSD1_BLK2_CFG_W2_REG 148 -#define AML_VIU_OSD1_BLK3_CFG_W2_REG 164 -#define AML_VIU_OSD_BLK_CFG_W2_Y_END_MASK (0x1fff << 16) -#define AML_VIU_OSD_BLK_CFG_W2_Y_END_SHIFT 16 -#define AML_VIU_OSD_BLK_CFG_W2_Y_START_MASK 0x1fff -#define AML_VIU_OSD_BLK_CFG_W2_Y_START_SHIFT 0 - -#define AML_VIU_OSD1_BLK0_CFG_W3_REG 120 -#define AML_VIU_OSD1_BLK1_CFG_W3_REG 136 -#define AML_VIU_OSD1_BLK2_CFG_W3_REG 152 -#define AML_VIU_OSD1_BLK3_CFG_W3_REG 168 -#define AML_VIU_OSD_BLK_CFG_W3_H_END_MASK (0xfff << 16) -#define AML_VIU_OSD_BLK_CFG_W3_H_END_SHIFT 16 -#define AML_VIU_OSD_BLK_CFG_W3_H_START_MASK 0xfff -#define AML_VIU_OSD_BLK_CFG_W3_H_START_SHIFT 0 - -#define AML_VIU_OSD1_BLK0_CFG_W4_REG 76 -#define AML_VIU_OSD1_BLK1_CFG_W4_REG 80 -#define AML_VIU_OSD1_BLK2_CFG_W4_REG 84 -#define AML_VIU_OSD1_BLK3_CFG_W4_REG 88 -#define AML_VIU_OSD_BLK_CFG_W4_V_END_MASK (0xfff << 16) -#define AML_VIU_OSD_BLK_CFG_W4_V_END_SHIFT 16 -#define AML_VIU_OSD_BLK_CFG_W4_V_START_MASK 0xfff -#define AML_VIU_OSD_BLK_CFG_W4_V_START_SHIFT 0 - -#define AML_VIU_OSD1_FIFO_CTRL_REG 172 -#define AML_VIU_OSD_FIFO_CTRL_DEPTH_MASK (0x3f << 12) -#define AML_VIU_OSD_FIFO_CTRL_DEPTH_SHIFT 12 -#define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_MASK (3 << 10) -#define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_24 (0 << 10) -#define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_32 (1 << 10) -#define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_48 (2 << 10) -#define AML_VIU_OSD_FIFO_CTRL_BURST_LEN_64 (3 << 10) -#define AML_VIU_OSD_FIFO_CTRL_HOLD_LINES_MASK (0x1f << 5) -#define AML_VIU_OSD_FIFO_CTRL_HOLD_LINES_SHIFT 5 -#define AML_VIU_OSD_FIFO_CTRL_URGENT (1 << 0) - -/* OSD2 field meanings are the same as OSD1 */ -#define AML_VIU_OSD2_CTRL_REG 192 -#define AML_VIU_OSD2_BLK0_CFG_W0_REG 236 -#define AML_VIU_OSD2_BLK1_CFG_W0_REG 252 -#define AML_VIU_OSD2_BLK2_CFG_W0_REG 268 -#define AML_VIU_OSD2_BLK3_CFG_W0_REG 284 -#define AML_VIU_OSD2_BLK0_CFG_W1_REG 240 -#define AML_VIU_OSD2_BLK1_CFG_W1_REG 256 -#define AML_VIU_OSD2_BLK2_CFG_W1_REG 272 -#define AML_VIU_OSD2_BLK3_CFG_W1_REG 288 -#define AML_VIU_OSD2_BLK0_CFG_W2_REG 244 -#define AML_VIU_OSD2_BLK1_CFG_W2_REG 260 -#define AML_VIU_OSD2_BLK2_CFG_W2_REG 276 -#define AML_VIU_OSD2_BLK3_CFG_W2_REG 292 -#define AML_VIU_OSD2_BLK0_CFG_W3_REG 248 -#define AML_VIU_OSD2_BLK1_CFG_W3_REG 264 -#define AML_VIU_OSD2_BLK2_CFG_W3_REG 280 -#define AML_VIU_OSD2_BLK3_CFG_W3_REG 296 -#define AML_VIU_OSD2_BLK0_CFG_W4_REG 400 -#define AML_VIU_OSD2_BLK1_CFG_W4_REG 404 -#define AML_VIU_OSD2_BLK2_CFG_W4_REG 408 -#define AML_VIU_OSD2_BLK3_CFG_W4_REG 412 -#define AML_VIU_OSD2_FIFO_CTRL_REG 300 - -#define AML_VPP_MISC_REG 152 -#define AML_VPP_MISC_OSD2_PREBLEND (1 << 17) -#define AML_VPP_MISC_OSD1_PREBLEND (1 << 16) -#define AML_VPP_MISC_VD2_PREBLEND (1 << 15) -#define AML_VPP_MISC_VD1_PREBLEND (1 << 14) -#define AML_VPP_MISC_OSD2_POSTBLEND (1 << 13) -#define AML_VPP_MISC_OSD1_POSTBLEND (1 << 12) -#define AML_VPP_MISC_VD2_POSTBLEND (1 << 11) -#define AML_VPP_MISC_VD1_POSTBLEND (1 << 10) -#define AML_VPP_MISC_POSTBLEND_EN (1 << 7) -#define AML_VPP_MISC_PREBLEND_EN (1 << 6) - -#endif /* _ARM_AMLOGIC_AML8726_FB_H */ Index: head/sys/arm/amlogic/aml8726/aml8726_fb.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_fb.c +++ head/sys/arm/amlogic/aml8726/aml8726_fb.c @@ -1,469 +0,0 @@ -/*- - * Copyright 2013-2014 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 frame buffer driver. - * - * The current implementation has limited flexibility. - * For example only progressive scan is supported when - * using HDMI and the resolution / frame rate is not - * negotiated. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include "fb_if.h" - -enum aml8726_fb_output { - aml8726_unknown_fb_output, - aml8726_cvbs_fb_output, - aml8726_hdmi_fb_output, - aml8726_lcd_fb_output -}; - -struct aml8726_fb_clk { - uint32_t freq; - uint32_t video_pre; - uint32_t video_post; - uint32_t video_x; - uint32_t hdmi_tx; - uint32_t encp; - uint32_t enci; - uint32_t enct; - uint32_t encl; - uint32_t vdac0; - uint32_t vdac1; -}; - -struct aml8726_fb_softc { - device_t dev; - struct resource *res[4]; - struct mtx mtx; - void *ih_cookie; - struct fb_info info; - enum aml8726_fb_output output; - struct aml8726_fb_clk clk; -}; - -static struct resource_spec aml8726_fb_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* CANVAS */ - { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* VIU */ - { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* VPP */ - { SYS_RES_IRQ, 1, RF_ACTIVE }, /* INT_VIU_VSYNC */ - { -1, 0 } -}; - -#define AML_FB_LOCK(sc) mtx_lock(&(sc)->mtx) -#define AML_FB_UNLOCK(sc) mtx_unlock(&(sc)->mtx) -#define AML_FB_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "fb", MTX_DEF) -#define AML_FB_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define CAV_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CAV_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) -#define CAV_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ - (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -#define VIU_WRITE_4(sc, reg, val) bus_write_4((sc)->res[1], reg, (val)) -#define VIU_READ_4(sc, reg) bus_read_4((sc)->res[1], reg) - -#define VPP_WRITE_4(sc, reg, val) bus_write_4((sc)->res[2], reg, (val)) -#define VPP_READ_4(sc, reg) bus_read_4((sc)->res[2], reg) - -#define CLK_WRITE_4(sc, reg, val) bus_write_4((sc)->res[X], reg, (val)) -#define CLK_READ_4(sc, reg) bus_read_4((sc)->res[X], reg) - -#define AML_FB_CLK_FREQ_SD 1080 -#define AML_FB_CLK_FREQ_HD 1488 - -static void -aml8726_fb_cfg_output(struct aml8726_fb_softc *sc) -{ - /* XXX */ -} - -static void -aml8726_fb_cfg_video(struct aml8726_fb_softc *sc) -{ - uint32_t value; - - /* - * basic initialization - * - * The fifo depth is in units of 8 so programming 32 - * sets the depth to 256. - */ - - value = (32 << AML_VIU_OSD_FIFO_CTRL_DEPTH_SHIFT); - value |= AML_VIU_OSD_FIFO_CTRL_BURST_LEN_64; - value |= (4 << AML_VIU_OSD_FIFO_CTRL_HOLD_LINES_SHIFT); - - VIU_WRITE_4(sc, AML_VIU_OSD1_FIFO_CTRL_REG, value); - VIU_WRITE_4(sc, AML_VIU_OSD2_FIFO_CTRL_REG, value); - - value = VPP_READ_4(sc, AML_VPP_MISC_REG); - - value &= ~AML_VPP_MISC_PREBLEND_EN; - value |= AML_VPP_MISC_POSTBLEND_EN; - value &= ~(AML_VPP_MISC_OSD1_POSTBLEND | AML_VPP_MISC_OSD2_POSTBLEND - | AML_VPP_MISC_VD1_POSTBLEND | AML_VPP_MISC_VD2_POSTBLEND); - - VPP_WRITE_4(sc, AML_VPP_MISC_REG, value); - - value = AML_VIU_OSD_CTRL_OSD_EN; - value |= (0xff << AML_VIU_OSD_CTRL_GLOBAL_ALPHA_SHIFT); - - VIU_WRITE_4(sc, AML_VIU_OSD1_CTRL_REG, value); - VIU_WRITE_4(sc, AML_VIU_OSD2_CTRL_REG, value); - - /* color mode for OSD1 block 0 */ - - value = (AML_CAV_OSD1_INDEX << AML_VIU_OSD_BLK_CFG_W0_INDEX_SHIFT) - | AML_VIU_OSD_BLK_CFG_W0_LITTLE_ENDIAN - | AML_VIU_OSD_BLK_CFG_W0_BLKMODE_24 - | AML_VIU_OSD_BLK_CFG_W0_RGB_EN - | AML_VIU_OSD_BLK_CFG_W0_CMATRIX_RGB; - - VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W0_REG, value); - - /* geometry / scaling for OSD1 block 0 */ - - value = ((sc->info.fb_width - 1) << AML_VIU_OSD_BLK_CFG_W1_X_END_SHIFT) - & AML_VIU_OSD_BLK_CFG_W1_X_END_MASK; - value |= (0 << AML_VIU_OSD_BLK_CFG_W1_X_START_SHIFT) - & AML_VIU_OSD_BLK_CFG_W1_X_START_MASK; - - VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W1_REG, value); - - value = ((sc->info.fb_height - 1) << AML_VIU_OSD_BLK_CFG_W2_Y_END_SHIFT) - & AML_VIU_OSD_BLK_CFG_W2_Y_END_MASK; - value |= (0 << AML_VIU_OSD_BLK_CFG_W2_Y_START_SHIFT) - & AML_VIU_OSD_BLK_CFG_W2_Y_START_MASK; - - VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W2_REG, value); - - value = ((sc->info.fb_width - 1) << AML_VIU_OSD_BLK_CFG_W3_H_END_SHIFT) - & AML_VIU_OSD_BLK_CFG_W3_H_END_MASK; - value |= (0 << AML_VIU_OSD_BLK_CFG_W3_H_START_SHIFT) - & AML_VIU_OSD_BLK_CFG_W3_H_START_MASK; - - VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W3_REG, value); - - value = ((sc->info.fb_height - 1) << AML_VIU_OSD_BLK_CFG_W4_V_END_SHIFT) - & AML_VIU_OSD_BLK_CFG_W4_V_END_MASK; - value |= (0 << AML_VIU_OSD_BLK_CFG_W4_V_START_SHIFT) - & AML_VIU_OSD_BLK_CFG_W4_V_START_MASK; - - VIU_WRITE_4(sc, AML_VIU_OSD1_BLK0_CFG_W4_REG, value); - - /* Enable the OSD block now that it's fully configured */ - - value = VIU_READ_4(sc, AML_VIU_OSD1_CTRL_REG); - - value &= ~AML_VIU_OSD_CTRL_OSD_BLK_EN_MASK; - value |= 1 << AML_VIU_OSD_CTRL_OSD_BLK_EN_SHIFT; - - VIU_WRITE_4(sc, AML_VIU_OSD1_CTRL_REG, value); - - /* enable video processing of OSD1 */ - - value = VPP_READ_4(sc, AML_VPP_MISC_REG); - - value |= AML_VPP_MISC_OSD1_POSTBLEND; - - VPP_WRITE_4(sc, AML_VPP_MISC_REG, value); -} - -static void -aml8726_fb_cfg_canvas(struct aml8726_fb_softc *sc) -{ - uint32_t value; - uint32_t width; - - /* - * The frame buffer address and width are programmed in units of 8 - * (meaning they need to be aligned and the actual values divided - * by 8 prior to programming the hardware). - */ - - width = (uint32_t)sc->info.fb_stride / 8; - - /* lower bits of the width */ - value = (width << AML_CAV_LUT_DATAL_WIDTH_SHIFT) & - AML_CAV_LUT_DATAL_WIDTH_MASK; - - /* physical address */ - value |= (uint32_t)sc->info.fb_pbase / 8; - - CAV_WRITE_4(sc, AML_CAV_LUT_DATAL_REG, value); - - /* upper bits of the width */ - value = ((width >> AML_CAV_LUT_DATAL_WIDTH_WIDTH) << - AML_CAV_LUT_DATAH_WIDTH_SHIFT) & AML_CAV_LUT_DATAH_WIDTH_MASK; - - /* height */ - value |= ((uint32_t)sc->info.fb_height << - AML_CAV_LUT_DATAH_HEIGHT_SHIFT) & AML_CAV_LUT_DATAH_HEIGHT_MASK; - - /* mode */ - value |= AML_CAV_LUT_DATAH_BLKMODE_LINEAR; - - CAV_WRITE_4(sc, AML_CAV_LUT_DATAH_REG, value); - - CAV_WRITE_4(sc, AML_CAV_LUT_ADDR_REG, (AML_CAV_LUT_ADDR_WR_EN | - (AML_CAV_OSD1_INDEX << AML_CAV_LUT_ADDR_INDEX_SHIFT))); - - CAV_BARRIER(sc, AML_CAV_LUT_ADDR_REG); -} - -static void -aml8726_fb_intr(void *arg) -{ - struct aml8726_fb_softc *sc = (struct aml8726_fb_softc *)arg; - - AML_FB_LOCK(sc); - - AML_FB_UNLOCK(sc); -} - -static int -aml8726_fb_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-fb")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 FB"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_fb_attach(device_t dev) -{ - struct aml8726_fb_softc *sc = device_get_softc(dev); - int error; - device_t child; - pcell_t prop; - phandle_t node; - - sc->dev = dev; - - sc->info.fb_name = device_get_nameunit(sc->dev); - - node = ofw_bus_get_node(dev); - - if (OF_getencprop(node, "width", &prop, sizeof(prop)) <= 0) { - device_printf(dev, "missing width attribute in FDT\n"); - return (ENXIO); - } - if ((prop % 8) != 0) { - device_printf(dev, - "width attribute in FDT must be a multiple of 8\n"); - return (ENXIO); - } - sc->info.fb_width = prop; - - if (OF_getencprop(node, "height", &prop, sizeof(prop)) <= 0) { - device_printf(dev, "missing height attribute in FDT\n"); - return (ENXIO); - } - sc->info.fb_height = prop; - - if (OF_getencprop(node, "depth", &prop, sizeof(prop)) <= 0) { - device_printf(dev, "missing depth attribute in FDT\n"); - return (ENXIO); - } - if (prop != 24) { - device_printf(dev, - "depth attribute in FDT is an unsupported value\n"); - return (ENXIO); - } - sc->info.fb_depth = prop; - sc->info.fb_bpp = prop; - - if (OF_getencprop(node, "linebytes", &prop, sizeof(prop)) <= 0) { - device_printf(dev, "missing linebytes attribute in FDT\n"); - return (ENXIO); - } - if ((prop % 8) != 0) { - device_printf(dev, - "linebytes attribute in FDT must be a multiple of 8\n"); - return (ENXIO); - } - if (prop < (sc->info.fb_width * 3)) { - device_printf(dev, - "linebytes attribute in FDT is too small\n"); - return (ENXIO); - } - sc->info.fb_stride = prop; - - if (OF_getencprop(node, "address", &prop, sizeof(prop)) <= 0) { - device_printf(dev, "missing address attribute in FDT\n"); - return (ENXIO); - } - if ((prop % 8) != 0) { - device_printf(dev, - "address attribute in FDT must be a multiple of 8\n"); - return (ENXIO); - } - sc->info.fb_pbase = prop; - sc->info.fb_size = sc->info.fb_height * sc->info.fb_stride; - sc->info.fb_vbase = (intptr_t)pmap_mapdev(sc->info.fb_pbase, - sc->info.fb_size); - - if (bus_alloc_resources(dev, aml8726_fb_spec, sc->res)) { - device_printf(dev, "could not allocate resources for device\n"); - pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size); - return (ENXIO); - } - - aml8726_fb_cfg_output(sc); - - aml8726_fb_cfg_video(sc); - - aml8726_fb_cfg_canvas(sc); - - AML_FB_LOCK_INIT(sc); - - error = bus_setup_intr(dev, sc->res[3], INTR_TYPE_MISC | INTR_MPSAFE, - NULL, aml8726_fb_intr, sc, &sc->ih_cookie); - - if (error) { - device_printf(dev, "could not setup interrupt handler\n"); - goto fail; - } - - child = device_add_child(dev, "fbd", device_get_unit(dev)); - - if (!child) { - device_printf(dev, "could not add fbd\n"); - error = ENXIO; - goto fail; - } - - error = device_probe_and_attach(child); - - if (error) { - device_printf(dev, "could not attach fbd\n"); - goto fail; - } - - return (0); - -fail: - if (sc->ih_cookie) - bus_teardown_intr(dev, sc->res[3], sc->ih_cookie); - - AML_FB_LOCK_DESTROY(sc); - - bus_release_resources(dev, aml8726_fb_spec, sc->res); - - pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size); - - return (error); -} - -static int -aml8726_fb_detach(device_t dev) -{ - struct aml8726_fb_softc *sc = device_get_softc(dev); - - bus_generic_detach(dev); - - bus_teardown_intr(dev, sc->res[3], sc->ih_cookie); - - AML_FB_LOCK_DESTROY(sc); - - bus_release_resources(dev, aml8726_fb_spec, sc->res); - - pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size); - - return (0); -} - -static struct fb_info * -aml8726_fb_getinfo(device_t dev) -{ - struct aml8726_fb_softc *sc = device_get_softc(dev); - - return (&sc->info); -} - -static device_method_t aml8726_fb_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_fb_probe), - DEVMETHOD(device_attach, aml8726_fb_attach), - DEVMETHOD(device_detach, aml8726_fb_detach), - - /* FB interface */ - DEVMETHOD(fb_getinfo, aml8726_fb_getinfo), - - DEVMETHOD_END -}; - -static driver_t aml8726_fb_driver = { - "fb", - aml8726_fb_methods, - sizeof(struct aml8726_fb_softc), -}; - -static devclass_t aml8726_fb_devclass; - -DRIVER_MODULE(fb, simplebus, aml8726_fb_driver, aml8726_fb_devclass, 0, 0); Index: head/sys/arm/amlogic/aml8726/aml8726_gpio.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_gpio.c +++ head/sys/arm/amlogic/aml8726/aml8726_gpio.c @@ -1,370 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 GPIO driver. - * - * Note: The OEN register is active * low *. Setting a bit to zero - * enables the output driver, setting a bit to one disables the driver. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include - -#include "gpio_if.h" - -struct aml8726_gpio_softc { - device_t dev; - struct resource *res[3]; - struct mtx mtx; - uint32_t npins; - device_t busdev; -}; - -static struct resource_spec aml8726_gpio_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE }, /* oen */ - { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_SHAREABLE }, /* output */ - { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* input */ - { -1, 0 } -}; - -#define AML_GPIO_LOCK(sc) mtx_lock(&(sc)->mtx) -#define AML_GPIO_UNLOCK(sc) mtx_unlock(&(sc)->mtx) -#define AML_GPIO_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "gpio", MTX_DEF) -#define AML_GPIO_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define AML_GPIO_OE_N_REG 0 -#define AML_GPIO_OUT_REG 1 -#define AML_GPIO_IN_REG 2 - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[reg], 0, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[reg], 0) - -static int -aml8726_gpio_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-gpio")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 GPIO"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_gpio_attach(device_t dev) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - phandle_t node; - pcell_t prop; - - sc->dev = dev; - - node = ofw_bus_get_node(dev); - - if (OF_getencprop(node, "pin-count", - &prop, sizeof(prop)) <= 0) { - device_printf(dev, "missing pin-count attribute in FDT\n"); - return (ENXIO); - } - sc->npins = prop; - - if (sc->npins > 32) - return (ENXIO); - - if (bus_alloc_resources(dev, aml8726_gpio_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - /* - * The GPIOAO OUT bits occupy the upper word of the OEN register. - */ - if (rman_get_start(sc->res[1]) == rman_get_start(sc->res[0])) - if (sc->npins > 16) { - device_printf(dev, - "too many pins for overlapping OEN and OUT\n"); - bus_release_resources(dev, aml8726_gpio_spec, sc->res); - return (ENXIO); - } - - AML_GPIO_LOCK_INIT(sc); - - sc->busdev = gpiobus_attach_bus(dev); - if (sc->busdev == NULL) { - AML_GPIO_LOCK_DESTROY(sc); - bus_release_resources(dev, aml8726_gpio_spec, sc->res); - return (ENXIO); - } - - return (0); -} - -static int -aml8726_gpio_detach(device_t dev) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - - gpiobus_detach_bus(dev); - - AML_GPIO_LOCK_DESTROY(sc); - - bus_release_resources(dev, aml8726_gpio_spec, sc->res); - - return (0); -} - -static device_t -aml8726_gpio_get_bus(device_t dev) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - - return (sc->busdev); -} - -static int -aml8726_gpio_pin_max(device_t dev, int *maxpin) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - - *maxpin = (int)sc->npins; - - return (0); -} - -/* Get a specific pin's capabilities. */ -static int -aml8726_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - - if (pin >= sc->npins) - return (EINVAL); - - *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT); - - return (0); -} - -/* Get a specific pin's name. */ -static int -aml8726_gpio_pin_getname(device_t dev, uint32_t pin, char *name) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - - if (pin >= sc->npins) - return (EINVAL); - - snprintf(name, GPIOMAXNAME, "%s.%u", ofw_bus_get_name(dev), pin); - - return (0); -} - -/* Get a specific pin's current in/out state. */ -static int -aml8726_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - uint32_t mask = 1U << pin; - - if (pin >= sc->npins) - return (EINVAL); - - if ((CSR_READ_4(sc, AML_GPIO_OE_N_REG) & mask) == 0) { - /* output */ - *flags = GPIO_PIN_OUTPUT; - } else - /* input */ - *flags = GPIO_PIN_INPUT; - - return (0); -} - -/* Set a specific pin's in/out state. */ -static int -aml8726_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - uint32_t mask = 1U << pin; - - if (pin >= sc->npins) - return (EINVAL); - - AML_GPIO_LOCK(sc); - - if ((flags & GPIO_PIN_OUTPUT) != 0) { - /* Output. Turn on driver. */ - CSR_WRITE_4(sc, AML_GPIO_OE_N_REG, - (CSR_READ_4(sc, AML_GPIO_OE_N_REG) & ~mask)); - } else { - /* Input. Turn off driver. */ - CSR_WRITE_4(sc, AML_GPIO_OE_N_REG, - (CSR_READ_4(sc, AML_GPIO_OE_N_REG) | mask)); - } - - AML_GPIO_UNLOCK(sc); - - return (0); -} - -/* Set a specific output pin's value. */ -static int -aml8726_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - uint32_t mask; - - if (pin >= sc->npins || value > 1) - return (EINVAL); - - /* - * The GPIOAO OUT bits occupy the upper word of the OEN register. - */ - if (rman_get_start(sc->res[1]) == rman_get_start(sc->res[0])) - pin += 16; - - mask = 1U << pin; - - AML_GPIO_LOCK(sc); - - CSR_WRITE_4(sc, AML_GPIO_OUT_REG, - ((CSR_READ_4(sc, AML_GPIO_OUT_REG) & ~mask) | (value << pin))); - - AML_GPIO_UNLOCK(sc); - - return (0); -} - -/* Get a specific pin's input value. */ -static int -aml8726_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - uint32_t mask = 1U << pin; - - if (pin >= sc->npins) - return (EINVAL); - - *value = (CSR_READ_4(sc, AML_GPIO_IN_REG) & mask) ? 1 : 0; - - return (0); -} - -/* Toggle a pin's output value. */ -static int -aml8726_gpio_pin_toggle(device_t dev, uint32_t pin) -{ - struct aml8726_gpio_softc *sc = device_get_softc(dev); - uint32_t mask; - - if (pin >= sc->npins) - return (EINVAL); - - /* - * The GPIOAO OUT bits occupy the upper word of the OEN register. - */ - if (rman_get_start(sc->res[1]) == rman_get_start(sc->res[0])) - pin += 16; - - mask = 1U << pin; - - AML_GPIO_LOCK(sc); - - CSR_WRITE_4(sc, AML_GPIO_OUT_REG, - CSR_READ_4(sc, AML_GPIO_OUT_REG) ^ mask); - - AML_GPIO_UNLOCK(sc); - - return (0); -} - -static phandle_t -aml8726_gpio_get_node(device_t bus, device_t dev) -{ - - /* We only have one child, the GPIO bus, which needs our own node. */ - return (ofw_bus_get_node(bus)); -} - -static device_method_t aml8726_gpio_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_gpio_probe), - DEVMETHOD(device_attach, aml8726_gpio_attach), - DEVMETHOD(device_detach, aml8726_gpio_detach), - - /* GPIO interface */ - DEVMETHOD(gpio_get_bus, aml8726_gpio_get_bus), - DEVMETHOD(gpio_pin_max, aml8726_gpio_pin_max), - DEVMETHOD(gpio_pin_getname, aml8726_gpio_pin_getname), - DEVMETHOD(gpio_pin_getflags, aml8726_gpio_pin_getflags), - DEVMETHOD(gpio_pin_getcaps, aml8726_gpio_pin_getcaps), - DEVMETHOD(gpio_pin_setflags, aml8726_gpio_pin_setflags), - DEVMETHOD(gpio_pin_get, aml8726_gpio_pin_get), - DEVMETHOD(gpio_pin_set, aml8726_gpio_pin_set), - DEVMETHOD(gpio_pin_toggle, aml8726_gpio_pin_toggle), - - /* ofw_bus interface */ - DEVMETHOD(ofw_bus_get_node, aml8726_gpio_get_node), - - DEVMETHOD_END -}; - -static driver_t aml8726_gpio_driver = { - "gpio", - aml8726_gpio_methods, - sizeof(struct aml8726_gpio_softc), -}; - -static devclass_t aml8726_gpio_devclass; - -DRIVER_MODULE(aml8726_gpio, simplebus, aml8726_gpio_driver, - aml8726_gpio_devclass, 0, 0); Index: head/sys/arm/amlogic/aml8726/aml8726_i2c.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_i2c.c +++ head/sys/arm/amlogic/aml8726/aml8726_i2c.c @@ -1,282 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 I2C driver. - * - * Currently this implementation doesn't take full advantage of the hardware. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include "iicbb_if.h" - -struct aml8726_iic_softc { - device_t dev; - struct resource *res[1]; - struct mtx mtx; - device_t iicbb; -}; - -static struct resource_spec aml8726_iic_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, 0 } -}; - -#define AML_I2C_LOCK(sc) mtx_lock(&(sc)->mtx) -#define AML_I2C_UNLOCK(sc) mtx_unlock(&(sc)->mtx) -#define AML_I2C_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "i2c", MTX_DEF) -#define AML_I2C_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define AML_I2C_CTRL_REG 0 -#define AML_I2C_MANUAL_SDA_I (1 << 26) -#define AML_I2C_MANUAL_SCL_I (1 << 25) -#define AML_I2C_MANUAL_SDA_O (1 << 24) -#define AML_I2C_MANUAL_SCL_O (1 << 23) -#define AML_I2C_MANUAL_EN (1 << 22) - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) - -static int -aml8726_iic_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,meson6-i2c")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 I2C"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_iic_attach(device_t dev) -{ - struct aml8726_iic_softc *sc = device_get_softc(dev); - int error; - - sc->dev = dev; - - if (bus_alloc_resources(dev, aml8726_iic_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - AML_I2C_LOCK_INIT(sc); - - sc->iicbb = device_add_child(dev, "iicbb", -1); - - if (sc->iicbb == NULL) { - device_printf(dev, "could not add iicbb\n"); - error = ENXIO; - goto fail; - } - - error = device_probe_and_attach(sc->iicbb); - - if (error) { - device_printf(dev, "could not attach iicbb\n"); - goto fail; - } - - return (0); - -fail: - AML_I2C_LOCK_DESTROY(sc); - bus_release_resources(dev, aml8726_iic_spec, sc->res); - - return (error); -} - -static int -aml8726_iic_detach(device_t dev) -{ - struct aml8726_iic_softc *sc = device_get_softc(dev); - device_t child; - - /* - * Detach the children before recursively deleting - * in case a child has a pointer to a grandchild - * which is used by the child's detach routine. - * - * Remember the child before detaching so we can - * delete it (bus_generic_detach indirectly zeroes - * sc->child_dev). - */ - child = sc->iicbb; - bus_generic_detach(dev); - if (child) - device_delete_child(dev, child); - - AML_I2C_LOCK_DESTROY(sc); - - bus_release_resources(dev, aml8726_iic_spec, sc->res); - - return (0); -} - -static void -aml8726_iic_child_detached(device_t dev, device_t child) -{ - struct aml8726_iic_softc *sc = device_get_softc(dev); - - if (child == sc->iicbb) - sc->iicbb = NULL; -} - -static int -aml8726_iic_callback(device_t dev, int index, caddr_t data) -{ - - return (0); -} - -static int -aml8726_iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) -{ - struct aml8726_iic_softc *sc = device_get_softc(dev); - - AML_I2C_LOCK(sc); - - CSR_WRITE_4(sc, AML_I2C_CTRL_REG, - (CSR_READ_4(sc, AML_I2C_CTRL_REG) | AML_I2C_MANUAL_SDA_O | - AML_I2C_MANUAL_SCL_O | AML_I2C_MANUAL_EN)); - - AML_I2C_UNLOCK(sc); - - /* Wait for 10 usec */ - DELAY(10); - - return (IIC_ENOADDR); -} - -static int -aml8726_iic_getscl(device_t dev) -{ - struct aml8726_iic_softc *sc = device_get_softc(dev); - - return (CSR_READ_4(sc, AML_I2C_CTRL_REG) & AML_I2C_MANUAL_SCL_I); -} - -static int -aml8726_iic_getsda(device_t dev) -{ - struct aml8726_iic_softc *sc = device_get_softc(dev); - - return (CSR_READ_4(sc, AML_I2C_CTRL_REG) & AML_I2C_MANUAL_SDA_I); -} - -static void -aml8726_iic_setscl(device_t dev, int val) -{ - struct aml8726_iic_softc *sc = device_get_softc(dev); - - AML_I2C_LOCK(sc); - - CSR_WRITE_4(sc, AML_I2C_CTRL_REG, ((CSR_READ_4(sc, AML_I2C_CTRL_REG) & - ~AML_I2C_MANUAL_SCL_O) | (val ? AML_I2C_MANUAL_SCL_O : 0) | - AML_I2C_MANUAL_EN)); - - AML_I2C_UNLOCK(sc); -} - -static void -aml8726_iic_setsda(device_t dev, int val) -{ - struct aml8726_iic_softc *sc = device_get_softc(dev); - - AML_I2C_LOCK(sc); - - CSR_WRITE_4(sc, AML_I2C_CTRL_REG, ((CSR_READ_4(sc, AML_I2C_CTRL_REG) & - ~AML_I2C_MANUAL_SDA_O) | (val ? AML_I2C_MANUAL_SDA_O : 0) | - AML_I2C_MANUAL_EN)); - - AML_I2C_UNLOCK(sc); -} - -static device_method_t aml8726_iic_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_iic_probe), - DEVMETHOD(device_attach, aml8726_iic_attach), - DEVMETHOD(device_detach, aml8726_iic_detach), - - /* bus interface */ - DEVMETHOD(bus_child_detached, aml8726_iic_child_detached), - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - /* IICBB interface */ - DEVMETHOD(iicbb_callback, aml8726_iic_callback), - DEVMETHOD(iicbb_reset, aml8726_iic_reset), - - DEVMETHOD(iicbb_getscl, aml8726_iic_getscl), - DEVMETHOD(iicbb_getsda, aml8726_iic_getsda), - DEVMETHOD(iicbb_setscl, aml8726_iic_setscl), - DEVMETHOD(iicbb_setsda, aml8726_iic_setsda), - - DEVMETHOD_END -}; - -static driver_t aml8726_iic_driver = { - "aml8726_iic", - aml8726_iic_methods, - sizeof(struct aml8726_iic_softc), -}; - -static devclass_t aml8726_iic_devclass; - -DRIVER_MODULE(aml8726_iic, simplebus, aml8726_iic_driver, - aml8726_iic_devclass, 0, 0); -DRIVER_MODULE(iicbb, aml8726_iic, iicbb_driver, iicbb_devclass, 0, 0); -MODULE_DEPEND(aml8726_iic, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); -MODULE_VERSION(aml8726_iic, 1); Index: head/sys/arm/amlogic/aml8726/aml8726_identsoc.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_identsoc.c +++ head/sys/arm/amlogic/aml8726/aml8726_identsoc.c @@ -1,142 +0,0 @@ -/*- - * Copyright 2015 John Wehle - * 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. - * - */ - -/* - * Amlogic aml8726 SoC identification. - * - * The SoC identification is used by some of the drivers in order to - * handle hardware differences so the identification needs to happen - * early in the boot process (e.g. before SMP startup). - * - * It's expected that the register addresses for identifying the SoC - * are set in stone. - * - * Currently missing an entry for the aml8726-m and doesn't distinguish - * between the m801, m802, m805, s802, s805, and s812 which are all - * variations of the aml8726-m8. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -uint32_t aml8726_soc_hw_rev = AML_SOC_HW_REV_UNKNOWN; -uint32_t aml8726_soc_metal_rev = AML_SOC_METAL_REV_UNKNOWN; - -static const struct { - uint32_t hw_rev; - char *desc; -} aml8726_soc_desc[] = { - { AML_SOC_HW_REV_M3, "aml8726-m3" }, - { AML_SOC_HW_REV_M6, "aml8726-m6" }, - { AML_SOC_HW_REV_M6TV, "aml8726-m6tv" }, - { AML_SOC_HW_REV_M6TVL, "aml8726-m6tvl" }, - { AML_SOC_HW_REV_M8, "aml8726-m8" }, - { AML_SOC_HW_REV_M8B, "aml8726-m8b" }, - { 0xff, NULL } -}; - -static const struct { - uint32_t metal_rev; - char *desc; -} aml8726_m8_soc_rev[] = { - { AML_SOC_M8_METAL_REV_A, "A" }, - { AML_SOC_M8_METAL_REV_M2_A, "MarkII A" }, - { AML_SOC_M8_METAL_REV_B, "B" }, - { AML_SOC_M8_METAL_REV_C, "C" }, - { 0xff, NULL } -}; - -void -aml8726_identify_soc(void) -{ - int err; - struct resource res; - - memset(&res, 0, sizeof(res)); - - res.r_bustag = fdtbus_bs_tag; - - err = bus_space_map(res.r_bustag, AML_SOC_CBUS_BASE_ADDR, 0x100000, - 0, &res.r_bushandle); - - if (err) - panic("Could not allocate resource for SoC identification\n"); - - aml8726_soc_hw_rev = bus_read_4(&res, AML_SOC_HW_REV_REG); - - aml8726_soc_metal_rev = bus_read_4(&res, AML_SOC_METAL_REV_REG); - - bus_space_unmap(res.r_bustag, res.r_bushandle, 0x100000); -} - -static void -aml8726_identify_announce_soc(void *dummy) -{ - int i; - - for (i = 0; aml8726_soc_desc[i].desc; i++) - if (aml8726_soc_desc[i].hw_rev == aml8726_soc_hw_rev) - break; - - if (aml8726_soc_desc[i].desc == NULL) - panic("Amlogic unknown aml8726 SoC %#x\n", aml8726_soc_hw_rev); - - printf("Amlogic %s SoC", aml8726_soc_desc[i].desc); - - if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8) { - for (i = 0; aml8726_m8_soc_rev[i].desc; i++) - if (aml8726_m8_soc_rev[i].metal_rev == - aml8726_soc_metal_rev) - break; - - if (aml8726_m8_soc_rev[i].desc == NULL) - printf(", unknown rev %#x", aml8726_soc_metal_rev); - else - printf(", rev %s", aml8726_m8_soc_rev[i].desc); - } - - printf("\n"); -} - -SYSINIT(aml8726_identify_announce_soc, SI_SUB_CPU, SI_ORDER_SECOND, - aml8726_identify_announce_soc, NULL); Index: head/sys/arm/amlogic/aml8726/aml8726_if_dwc.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_if_dwc.c +++ head/sys/arm/amlogic/aml8726/aml8726_if_dwc.c @@ -1,98 +0,0 @@ -/*- - * Copyright (c) 2015 Ganbold Tsagaankhuu - * 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. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "if_dwc_if.h" - -static int -aml8726_if_dwc_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - if (!ofw_bus_is_compatible(dev, "amlogic,meson6-dwmac")) - return (ENXIO); - device_set_desc(dev, "Amlogic Meson Gigabit Ethernet Controller"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_if_dwc_init(device_t dev) -{ - - return (0); -} - -static int -aml8726_if_dwc_mac_type(device_t dev) -{ - - return (DWC_GMAC_NORMAL_DESC); -} - -static int -aml8726_if_dwc_mii_clk(device_t dev) -{ - - return (GMAC_MII_CLK_100_150M_DIV62); -} - -static device_method_t aml8726_dwc_methods[] = { - DEVMETHOD(device_probe, aml8726_if_dwc_probe), - - DEVMETHOD(if_dwc_init, aml8726_if_dwc_init), - DEVMETHOD(if_dwc_mac_type, aml8726_if_dwc_mac_type), - DEVMETHOD(if_dwc_mii_clk, aml8726_if_dwc_mii_clk), - - DEVMETHOD_END -}; - -static devclass_t aml8726_dwc_devclass; - -extern driver_t dwc_driver; - -DEFINE_CLASS_1(dwc, aml8726_dwc_driver, aml8726_dwc_methods, - sizeof(struct dwc_softc), dwc_driver); -DRIVER_MODULE(aml8726_dwc, simplebus, aml8726_dwc_driver, - aml8726_dwc_devclass, 0, 0); - -MODULE_DEPEND(aml8726_dwc, dwc, 1, 1, 1); Index: head/sys/arm/amlogic/aml8726/aml8726_l2cache.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_l2cache.c +++ head/sys/arm/amlogic/aml8726/aml8726_l2cache.c @@ -1,92 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * All rights reserved. - * - * Based on omap4_l2cache.c by Olivier Houchard - * - * 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$ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -void -platform_pl310_init(struct pl310_softc *sc) -{ - uint32_t aux; - - aux = pl310_read4(sc, PL310_AUX_CTRL); - - /* - * The Amlogic Linux platform code enables via AUX: - * - * Early BRESP - * Full Line of Zero (which must match processor setting) - * Data Prefetch - * - * and additionally on the m6 enables: - * - * Instruction Prefetch - * - * For the moment we only enable Data Prefetch ... - * further refinements can happen as things mature. - */ - - /* - * Disable instruction prefetch. - */ - aux &= ~AUX_CTRL_INSTR_PREFETCH; - - /* - * Enable data prefetch. - */ - aux |= AUX_CTRL_DATA_PREFETCH; - - pl310_write4(sc, PL310_AUX_CTRL, aux); -} - -void -platform_pl310_write_ctrl(struct pl310_softc *sc, uint32_t val) -{ - - pl310_write4(sc, PL310_CTRL, val); -} - -void -platform_pl310_write_debug(struct pl310_softc *sc, uint32_t val) -{ - - pl310_write4(sc, PL310_DEBUG_CTRL, val); -} Index: head/sys/arm/amlogic/aml8726/aml8726_machdep.h =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_machdep.h +++ head/sys/arm/amlogic/aml8726/aml8726_machdep.h @@ -1,41 +0,0 @@ -/*- - * Copyright 2014 John Wehle - * 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 _ARM_AMLOGIC_AML8726_MACHDEP_H -#define _ARM_AMLOGIC_AML8726_MACHDEP_H - -/* - * The aobus kvm base is supplied as a global variable * only * - * for the convience of the aml8726 UART console driver which - * is available for use to debug early boot code. - * - * This variable should not be used elsewhere. - */ -extern vm_offset_t aml8726_aobus_kva_base; - -#endif /* _ARM_AMLOGIC_AML8726_MACHDEP_H */ Index: head/sys/arm/amlogic/aml8726/aml8726_machdep.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_machdep.c +++ head/sys/arm/amlogic/aml8726/aml8726_machdep.c @@ -1,196 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - */ - -#include "opt_global.h" - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_platform.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#if defined(SOCDEV_PA) && defined(SOCDEV_VA) -vm_offset_t aml8726_aobus_kva_base = SOCDEV_VA; -#else -vm_offset_t aml8726_aobus_kva_base; -#endif - -static void -aml8726_fixup_busfreq(void) -{ - phandle_t node; - pcell_t freq, prop; - ssize_t len; - - /* - * Set the bus-frequency for the SoC simple-bus if it - * needs updating (meaning the current frequency is zero). - */ - - if ((freq = aml8726_clkmsr_bus_frequency()) == 0 || - (node = OF_finddevice("/soc")) == 0 || - fdt_is_compatible_strict(node, "simple-bus") == 0) - while (1); - - freq = cpu_to_fdt32(freq); - - len = OF_getencprop(node, "bus-frequency", &prop, sizeof(prop)); - if ((len / sizeof(prop)) == 1 && prop == 0) - OF_setprop(node, "bus-frequency", (void *)&freq, sizeof(freq)); -} - -vm_offset_t -platform_lastaddr(void) -{ - - return (devmap_lastaddr()); -} - -void -platform_probe_and_attach(void) -{ -} - -void -platform_gpio_init(void) -{ - - /* - * The UART console driver used for debugging early boot code - * needs to know the virtual base address of the aobus. It's - * expected to equal SOCDEV_VA prior to initarm calling setttb - * ... afterwards it needs to be updated due to the new page - * tables. - * - * This means there's a deadzone in initarm between setttb - * and platform_gpio_init during which printf can't be used. - */ - aml8726_aobus_kva_base = - (vm_offset_t)devmap_ptov(0xc8100000, 0x100000); - - /* - * The hardware mux used by clkmsr is unique to the SoC (though - * currently clk81 is at a fixed location, however that might - * change in the future). - */ - aml8726_identify_soc(); - - /* - * My aml8726-m3 development box which identifies the CPU as - * a Cortex A9-r2 rev 4 randomly locks up during boot when WFI - * is used. - */ - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M3: - cpufuncs.cf_sleep = (void *)cpufunc_nullop; - break; - default: - break; - } - - /* - * This FDT fixup should arguably be called through fdt_fixup_table, - * however currently there's no mechanism to specify a fixup which - * should always be invoked. - * - * It needs to be called prior to the console being initialized which - * is why it's called here, rather than from platform_late_init. - */ - aml8726_fixup_busfreq(); -} - -void -platform_late_init(void) -{ -} - -/* - * Construct static devmap entries to map out the core - * peripherals using 1mb section mappings. - */ -int -platform_devmap_init(void) -{ - - devmap_add_entry(0xc1100000, 0x200000); /* cbus */ - devmap_add_entry(0xc4200000, 0x100000); /* pl310 */ - devmap_add_entry(0xc4300000, 0x100000); /* periph */ - devmap_add_entry(0xc8000000, 0x100000); /* apbbus */ - devmap_add_entry(0xc8100000, 0x100000); /* aobus */ - devmap_add_entry(0xc9000000, 0x800000); /* ahbbus */ - devmap_add_entry(0xd9000000, 0x100000); /* ahb */ - devmap_add_entry(0xda000000, 0x100000); /* secbus */ - - return (0); -} - -#ifndef INTRNG -#ifndef DEV_GIC -static int -fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, - int *pol) -{ - - /* - * The single core chips have just an Amlogic PIC. - */ - if (!fdt_is_compatible_strict(node, "amlogic,aml8726-pic")) - return (ENXIO); - - *interrupt = fdt32_to_cpu(intr[1]); - *trig = INTR_TRIGGER_EDGE; - *pol = INTR_POLARITY_HIGH; - - return (0); -} -#endif - -fdt_pic_decode_t fdt_pic_table[] = { -#ifdef DEV_GIC - &gic_decode_fdt, -#else - &fdt_pic_decode_ic, -#endif - NULL -}; -#endif /* INTRNG */ Index: head/sys/arm/amlogic/aml8726/aml8726_mmc.h =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_mmc.h +++ head/sys/arm/amlogic/aml8726/aml8726_mmc.h @@ -1,122 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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 _ARM_AMLOGIC_AML8726_MMC_H -#define _ARM_AMLOGIC_AML8726_MMC_H - -#define AML_MMC_ALIGN_DMA 4 -#define AML_MMC_MAX_DMA 4096 - -/* - * Timeouts are in milliseconds - * - * Read and write are per section 4.6.2 of the: - * - * SD Specifications Part 1 - * Physical Layer Simplified Specification - * Version 4.10 - */ -#define AML_MMC_CMD_TIMEOUT 50 -#define AML_MMC_READ_TIMEOUT 100 -#define AML_MMC_WRITE_TIMEOUT 500 -#define AML_MMC_MAX_TIMEOUT 5000 - -#define AML_MMC_CMD_ARGUMENT_REG 0 - -#define AML_MMC_CMD_SEND_REG 4 -#define AML_MMC_CMD_REP_PKG_CNT_MASK (0xffU << 24) -#define AML_MMC_CMD_REP_PKG_CNT_SHIFT 24 -#define AML_MMC_CMD_CMD_HAS_DATA (1 << 20) -#define AML_MMC_CMD_CHECK_DAT0_BUSY (1 << 19) -#define AML_MMC_CMD_RESP_CRC7_FROM_8 (1 << 18) -#define AML_MMC_CMD_RESP_HAS_DATA (1 << 17) -#define AML_MMC_CMD_RESP_NO_CRC7 (1 << 16) -#define AML_MMC_CMD_RESP_BITS_MASK (0xff << 8) -#define AML_MMC_CMD_RESP_BITS_SHIFT 8 -#define AML_MMC_CMD_START_BIT (0 << 7) -#define AML_MMC_CMD_TRANS_BIT_HOST (1 << 6) -#define AML_MMC_CMD_INDEX_MASK 0x3f -#define AML_MMC_CMD_INDEX_SHIFT 0 - -#define AML_MMC_CONFIG_REG 8 -#define AML_MMC_CONFIG_WR_CRC_STAT_MASK (7U << 29) -#define AML_MMC_CONFIG_WR_CRC_STAT_SHIFT 29 -#define AML_MMC_CONFIG_WR_DELAY_MASK (0x3f << 23) -#define AML_MMC_CONFIG_WR_DELAY_SHIFT 23 -#define AML_MMC_CONFIG_DMA_ENDIAN_MASK (3 << 21) -#define AML_MMC_CONFIG_DMA_ENDIAN_NC (0 << 21) -#define AML_MMC_CONFIG_DMA_ENDIAN_SB (1 << 21) -#define AML_MMC_CONFIG_DMA_ENDIAN_SW (2 << 21) -#define AML_MMC_CONFIG_DMA_ENDIAN_SBW (3 << 21) -#define AML_MMC_CONFIG_BUS_WIDTH_MASK (1 << 20) -#define AML_MMC_CONFIG_BUS_WIDTH_1 (0 << 20) -#define AML_MMC_CONFIG_BUS_WIDTH_4 (1 << 20) -#define AML_MMC_CONFIG_DATA_NEG_EDGE (1 << 19) -#define AML_MMC_CONFIG_DONT_DELAY_DATA (1 << 18) -#define AML_MMC_CONFIG_CMD_ARG_BITS_MASK (0x3f << 12) -#define AML_MMC_CONFIG_CMD_ARG_BITS_SHIFT 12 -#define AML_MMC_CONFIG_CMD_POS_EDGE (1 << 11) -#define AML_MMC_CONFIG_CMD_NO_CRC (1 << 10) -#define AML_MMC_CONFIG_CMD_CLK_DIV_MASK 0x3ff -#define AML_MMC_CONFIG_CMD_CLK_DIV_SHIFT 0 - -#define AML_MMC_IRQ_STATUS_REG 12 -#define AML_MMC_IRQ_STATUS_TIMER_CNT_MASK (0x1fffU << 19) -#define AML_MMC_IRQ_STATUS_TIMER_CNT_SHIFT 19 -#define AML_MMC_IRQ_STATUS_TIMER_EN (1 << 18) -#define AML_MMC_IRQ_STATUS_TIMEOUT_IRQ (1 << 16) -#define AML_MMC_IRQ_STATUS_CMD_DONE_IRQ (1 << 9) -#define AML_MMC_IRQ_STATUS_WR_CRC16_OK (1 << 7) -#define AML_MMC_IRQ_STATUS_RD_CRC16_OK (1 << 6) -#define AML_MMC_IRQ_STATUS_RESP_CRC7_OK (1 << 5) -#define AML_MMC_IRQ_STATUS_CMD_BUSY (1 << 4) -#define AML_MMC_IRQ_STATUS_CLEAR_IRQ 0x10700 - -#define AML_MMC_IRQ_CONFIG_REG 16 -#define AML_MMC_IRQ_CONFIG_SOFT_RESET (1 << 15) -#define AML_MMC_IRQ_CONFIG_CMD_DONE_EN (1 << 4) - -#define AML_MMC_MULT_CONFIG_REG 20 -#define AML_MMC_MULT_CONFIG_RESP_INDEX_MASK (0xf << 12) -#define AML_MMC_MULT_CONFIG_RESP_INDEX_SHIFT 12 -#define AML_MMC_MULT_CONFIG_RESP_READOUT_EN (1 << 8) -#define AML_MMC_MULT_CONFIG_STREAM_8_MODE (1 << 5) -#define AML_MMC_MULT_CONFIG_STREAM_EN (1 << 4) -#define AML_MMC_MULT_CONFIG_PORT_MASK 3 -#define AML_MMC_MULT_CONFIG_PORT_A 0 -#define AML_MMC_MULT_CONFIG_PORT_B 1 -#define AML_MMC_MULT_CONFIG_PORT_C 2 - -#define AML_MMC_DMA_ADDR_REG 24 - -#define AML_MMC_EXTENSION_REG 28 -#define AML_MMC_EXTENSION_NO_CRC16 (1 << 30) -#define AML_MMC_EXTENSION_PKT_SIZE_MASK (0x3fff << 16) -#define AML_MMC_EXTENSION_PKT_SIZE_SHIFT 16 - -#endif /* _ARM_AMLOGIC_AML8726_MMC_H */ Index: head/sys/arm/amlogic/aml8726/aml8726_mmc.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_mmc.c +++ head/sys/arm/amlogic/aml8726/aml8726_mmc.c @@ -1,1114 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 MMC host controller driver. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include -#include - -#include - -#include "gpio_if.h" -#include "mmcbr_if.h" - -struct aml8726_mmc_gpio { - device_t dev; - uint32_t pin; - uint32_t pol; -}; - -struct aml8726_mmc_softc { - device_t dev; - struct resource *res[2]; - struct mtx mtx; - struct callout ch; - uint32_t port; - unsigned int ref_freq; - struct aml8726_mmc_gpio pwr_en; - int voltages[2]; - struct aml8726_mmc_gpio vselect; - bus_dma_tag_t dmatag; - bus_dmamap_t dmamap; - void *ih_cookie; - struct mmc_host host; - int bus_busy; - struct mmc_command *cmd; - uint32_t stop_timeout; -}; - -static struct resource_spec aml8726_mmc_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { SYS_RES_IRQ, 0, RF_ACTIVE }, - { -1, 0 } -}; - -#define AML_MMC_LOCK(sc) mtx_lock(&(sc)->mtx) -#define AML_MMC_UNLOCK(sc) mtx_unlock(&(sc)->mtx) -#define AML_MMC_LOCK_ASSERT(sc) mtx_assert(&(sc)->mtx, MA_OWNED) -#define AML_MMC_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "mmc", MTX_DEF) -#define AML_MMC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) -#define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ - (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -#define PWR_ON_FLAG(pol) ((pol) == 0 ? GPIO_PIN_LOW : \ - GPIO_PIN_HIGH) -#define PWR_OFF_FLAG(pol) ((pol) == 0 ? GPIO_PIN_HIGH : \ - GPIO_PIN_LOW) - -#define MSECS_TO_TICKS(ms) (((ms)*hz)/1000 + 1) - -static void aml8726_mmc_timeout(void *arg); - -static unsigned int -aml8726_mmc_clk(phandle_t node) -{ - pcell_t prop; - ssize_t len; - phandle_t clk_node; - - len = OF_getencprop(node, "clocks", &prop, sizeof(prop)); - if ((len / sizeof(prop)) != 1 || prop == 0 || - (clk_node = OF_node_from_xref(prop)) == 0) - return (0); - - len = OF_getencprop(clk_node, "clock-frequency", &prop, sizeof(prop)); - if ((len / sizeof(prop)) != 1 || prop == 0) - return (0); - - return ((unsigned int)prop); -} - -static uint32_t -aml8726_mmc_freq(struct aml8726_mmc_softc *sc, uint32_t divisor) -{ - - return (sc->ref_freq / ((divisor + 1) * 2)); -} - -static uint32_t -aml8726_mmc_div(struct aml8726_mmc_softc *sc, uint32_t desired_freq) -{ - uint32_t divisor; - - divisor = sc->ref_freq / (desired_freq * 2); - - if (divisor == 0) - divisor = 1; - - divisor -= 1; - - if (aml8726_mmc_freq(sc, divisor) > desired_freq) - divisor += 1; - - if (divisor > (AML_MMC_CONFIG_CMD_CLK_DIV_MASK >> - AML_MMC_CONFIG_CMD_CLK_DIV_SHIFT)) { - divisor = AML_MMC_CONFIG_CMD_CLK_DIV_MASK >> - AML_MMC_CONFIG_CMD_CLK_DIV_SHIFT; - } - - return (divisor); -} - -static void -aml8726_mmc_mapmem(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - bus_addr_t *busaddrp; - - /* - * There should only be one bus space address since - * bus_dma_tag_create was called with nsegments = 1. - */ - - busaddrp = (bus_addr_t *)arg; - *busaddrp = segs->ds_addr; -} - -static int -aml8726_mmc_power_off(struct aml8726_mmc_softc *sc) -{ - - if (sc->pwr_en.dev == NULL) - return (0); - - return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, - PWR_OFF_FLAG(sc->pwr_en.pol))); -} - -static int -aml8726_mmc_power_on(struct aml8726_mmc_softc *sc) -{ - - if (sc->pwr_en.dev == NULL) - return (0); - - return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, - PWR_ON_FLAG(sc->pwr_en.pol))); -} - -static void -aml8726_mmc_soft_reset(struct aml8726_mmc_softc *sc, boolean_t enable_irq) -{ - uint32_t icr; - - icr = AML_MMC_IRQ_CONFIG_SOFT_RESET; - - if (enable_irq == true) - icr |= AML_MMC_IRQ_CONFIG_CMD_DONE_EN; - - CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, icr); - CSR_BARRIER(sc, AML_MMC_IRQ_CONFIG_REG); -} - -static int -aml8726_mmc_start_command(struct aml8726_mmc_softc *sc, struct mmc_command *cmd) -{ - struct mmc_ios *ios = &sc->host.ios; - bus_addr_t baddr; - uint32_t block_size; - uint32_t bus_width; - uint32_t cmdr; - uint32_t extr; - uint32_t mcfgr; - uint32_t nbits_per_pkg; - uint32_t timeout; - int error; - struct mmc_data *data; - - if (cmd->opcode > 0x3f) - return (MMC_ERR_INVALID); - - /* - * Ensure the hardware state machine is in a known state. - */ - aml8726_mmc_soft_reset(sc, true); - - /* - * Start and transmission bits are per section 4.7.2 of the: - * - * SD Specifications Part 1 - * Physical Layer Simplified Specification - * Version 4.10 - */ - cmdr = AML_MMC_CMD_START_BIT | AML_MMC_CMD_TRANS_BIT_HOST | cmd->opcode; - baddr = 0; - extr = 0; - mcfgr = sc->port; - timeout = AML_MMC_CMD_TIMEOUT; - - /* - * If this is a linked command, then use the previous timeout. - */ - if (cmd == cmd->mrq->stop && sc->stop_timeout) - timeout = sc->stop_timeout; - sc->stop_timeout = 0; - - if ((cmd->flags & MMC_RSP_136) != 0) { - cmdr |= AML_MMC_CMD_RESP_CRC7_FROM_8; - cmdr |= (133 << AML_MMC_CMD_RESP_BITS_SHIFT); - } else if ((cmd->flags & MMC_RSP_PRESENT) != 0) - cmdr |= (45 << AML_MMC_CMD_RESP_BITS_SHIFT); - - if ((cmd->flags & MMC_RSP_CRC) == 0) - cmdr |= AML_MMC_CMD_RESP_NO_CRC7; - - if ((cmd->flags & MMC_RSP_BUSY) != 0) - cmdr |= AML_MMC_CMD_CHECK_DAT0_BUSY; - - data = cmd->data; - - if (data && data->len && - (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) { - block_size = data->len; - - if ((data->flags & MMC_DATA_MULTI) != 0) { - block_size = MMC_SECTOR_SIZE; - if ((data->len % block_size) != 0) - return (MMC_ERR_INVALID); - } - - cmdr |= (((data->len / block_size) - 1) << - AML_MMC_CMD_REP_PKG_CNT_SHIFT); - - mcfgr |= (data->flags & MMC_DATA_STREAM) ? - AML_MMC_MULT_CONFIG_STREAM_EN : 0; - - /* - * The number of bits per package equals the number - * of data bits + the number of CRC bits. There are - * 16 bits of CRC calculate per bus line. - * - * A completed package appears to be detected by when - * a counter decremented by the width underflows, thus - * a value of zero always transfers 1 (or 4 bits depending - * on the mode) which is why bus_width is subtracted. - */ - bus_width = (ios->bus_width == bus_width_4) ? 4 : 1; - nbits_per_pkg = block_size * 8 + 16 * bus_width - bus_width; - if (nbits_per_pkg > 0x3fff) - return (MMC_ERR_INVALID); - - extr |= (nbits_per_pkg << AML_MMC_EXTENSION_PKT_SIZE_SHIFT); - - error = bus_dmamap_load(sc->dmatag, sc->dmamap, - data->data, data->len, aml8726_mmc_mapmem, &baddr, - BUS_DMA_NOWAIT); - if (error) - return (MMC_ERR_NO_MEMORY); - - if ((data->flags & MMC_DATA_READ) != 0) { - cmdr |= AML_MMC_CMD_RESP_HAS_DATA; - bus_dmamap_sync(sc->dmatag, sc->dmamap, - BUS_DMASYNC_PREREAD); - timeout = AML_MMC_READ_TIMEOUT * - (data->len / block_size); - } else { - cmdr |= AML_MMC_CMD_CMD_HAS_DATA; - bus_dmamap_sync(sc->dmatag, sc->dmamap, - BUS_DMASYNC_PREWRITE); - timeout = AML_MMC_WRITE_TIMEOUT * - (data->len / block_size); - } - - /* - * Stop terminates a multiblock read / write and thus - * can take as long to execute as an actual read / write. - */ - if (cmd->mrq->stop != NULL) - sc->stop_timeout = timeout; - } - - sc->cmd = cmd; - - cmd->error = MMC_ERR_NONE; - - if (timeout > AML_MMC_MAX_TIMEOUT) - timeout = AML_MMC_MAX_TIMEOUT; - - callout_reset(&sc->ch, MSECS_TO_TICKS(timeout), - aml8726_mmc_timeout, sc); - - CSR_WRITE_4(sc, AML_MMC_CMD_ARGUMENT_REG, cmd->arg); - CSR_WRITE_4(sc, AML_MMC_MULT_CONFIG_REG, mcfgr); - CSR_WRITE_4(sc, AML_MMC_EXTENSION_REG, extr); - CSR_WRITE_4(sc, AML_MMC_DMA_ADDR_REG, (uint32_t)baddr); - - CSR_WRITE_4(sc, AML_MMC_CMD_SEND_REG, cmdr); - CSR_BARRIER(sc, AML_MMC_CMD_SEND_REG); - - return (MMC_ERR_NONE); -} - -static void -aml8726_mmc_finish_command(struct aml8726_mmc_softc *sc, int mmc_error) -{ - int mmc_stop_error; - struct mmc_command *cmd; - struct mmc_command *stop_cmd; - struct mmc_data *data; - - AML_MMC_LOCK_ASSERT(sc); - - /* Clear all interrupts since the request is no longer in flight. */ - CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ); - CSR_BARRIER(sc, AML_MMC_IRQ_STATUS_REG); - - /* In some cases (e.g. finish called via timeout) this is a NOP. */ - callout_stop(&sc->ch); - - cmd = sc->cmd; - sc->cmd = NULL; - - cmd->error = mmc_error; - - data = cmd->data; - - if (data && data->len && - (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) { - if ((data->flags & MMC_DATA_READ) != 0) - bus_dmamap_sync(sc->dmatag, sc->dmamap, - BUS_DMASYNC_POSTREAD); - else - bus_dmamap_sync(sc->dmatag, sc->dmamap, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->dmatag, sc->dmamap); - } - - /* - * If there's a linked stop command, then start the stop command. - * In order to establish a known state attempt the stop command - * even if the original request encountered an error. - */ - - stop_cmd = (cmd->mrq->stop != cmd) ? cmd->mrq->stop : NULL; - - if (stop_cmd != NULL) { - mmc_stop_error = aml8726_mmc_start_command(sc, stop_cmd); - if (mmc_stop_error == MMC_ERR_NONE) { - AML_MMC_UNLOCK(sc); - return; - } - stop_cmd->error = mmc_stop_error; - } - - AML_MMC_UNLOCK(sc); - - /* Execute the callback after dropping the lock. */ - if (cmd->mrq) - cmd->mrq->done(cmd->mrq); -} - -static void -aml8726_mmc_timeout(void *arg) -{ - struct aml8726_mmc_softc *sc = (struct aml8726_mmc_softc *)arg; - - /* - * The command failed to complete in time so forcefully - * terminate it. - */ - aml8726_mmc_soft_reset(sc, false); - - /* - * Ensure the command has terminated before continuing on - * to things such as bus_dmamap_sync / bus_dmamap_unload. - */ - while ((CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG) & - AML_MMC_IRQ_STATUS_CMD_BUSY) != 0) - cpu_spinwait(); - - aml8726_mmc_finish_command(sc, MMC_ERR_TIMEOUT); -} - -static void -aml8726_mmc_intr(void *arg) -{ - struct aml8726_mmc_softc *sc = (struct aml8726_mmc_softc *)arg; - uint32_t cmdr; - uint32_t isr; - uint32_t mcfgr; - uint32_t previous_byte; - uint32_t resp; - int mmc_error; - unsigned int i; - - AML_MMC_LOCK(sc); - - isr = CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG); - cmdr = CSR_READ_4(sc, AML_MMC_CMD_SEND_REG); - - if (sc->cmd == NULL) - goto spurious; - - mmc_error = MMC_ERR_NONE; - - if ((isr & AML_MMC_IRQ_STATUS_CMD_DONE_IRQ) != 0) { - /* Check for CRC errors if the command has completed. */ - if ((cmdr & AML_MMC_CMD_RESP_NO_CRC7) == 0 && - (isr & AML_MMC_IRQ_STATUS_RESP_CRC7_OK) == 0) - mmc_error = MMC_ERR_BADCRC; - if ((cmdr & AML_MMC_CMD_RESP_HAS_DATA) != 0 && - (isr & AML_MMC_IRQ_STATUS_RD_CRC16_OK) == 0) - mmc_error = MMC_ERR_BADCRC; - if ((cmdr & AML_MMC_CMD_CMD_HAS_DATA) != 0 && - (isr & AML_MMC_IRQ_STATUS_WR_CRC16_OK) == 0) - mmc_error = MMC_ERR_BADCRC; - } else { -spurious: - - /* - * Clear spurious interrupts while leaving intacted any - * interrupts that may have occurred after we read the - * interrupt status register. - */ - - CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, - (AML_MMC_IRQ_STATUS_CLEAR_IRQ & isr)); - CSR_BARRIER(sc, AML_MMC_IRQ_STATUS_REG); - AML_MMC_UNLOCK(sc); - return; - } - - if ((cmdr & AML_MMC_CMD_RESP_BITS_MASK) != 0) { - mcfgr = sc->port; - mcfgr |= AML_MMC_MULT_CONFIG_RESP_READOUT_EN; - CSR_WRITE_4(sc, AML_MMC_MULT_CONFIG_REG, mcfgr); - - if ((cmdr & AML_MMC_CMD_RESP_CRC7_FROM_8) != 0) { - /* - * Controller supplies 135:8 instead of - * 127:0 so discard the leading 8 bits - * and provide a trailing 8 zero bits - * where the CRC belongs. - */ - - previous_byte = 0; - - for (i = 0; i < 4; i++) { - resp = CSR_READ_4(sc, AML_MMC_CMD_ARGUMENT_REG); - sc->cmd->resp[3 - i] = (resp << 8) | - previous_byte; - previous_byte = (resp >> 24) & 0xff; - } - } else - sc->cmd->resp[0] = CSR_READ_4(sc, - AML_MMC_CMD_ARGUMENT_REG); - } - - if ((isr & AML_MMC_IRQ_STATUS_CMD_BUSY) != 0 && - /* - * A multiblock operation may keep the hardware - * busy until stop transmission is executed. - */ - (isr & AML_MMC_IRQ_STATUS_CMD_DONE_IRQ) == 0) { - if (mmc_error == MMC_ERR_NONE) - mmc_error = MMC_ERR_FAILED; - - /* - * Issue a soft reset to terminate the command. - * - * Ensure the command has terminated before continuing on - * to things such as bus_dmamap_sync / bus_dmamap_unload. - */ - - aml8726_mmc_soft_reset(sc, false); - - while ((CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG) & - AML_MMC_IRQ_STATUS_CMD_BUSY) != 0) - cpu_spinwait(); - } - - aml8726_mmc_finish_command(sc, mmc_error); -} - -static int -aml8726_mmc_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-mmc")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 MMC"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_mmc_attach(device_t dev) -{ - struct aml8726_mmc_softc *sc = device_get_softc(dev); - char *function_name; - char *voltages; - char *voltage; - int error; - int nvoltages; - pcell_t prop[3]; - phandle_t node; - ssize_t len; - device_t child; - - sc->dev = dev; - - node = ofw_bus_get_node(dev); - - sc->ref_freq = aml8726_mmc_clk(node); - - if (sc->ref_freq == 0) { - device_printf(dev, "missing clocks attribute in FDT\n"); - return (ENXIO); - } - - /* - * The pins must be specified as part of the device in order - * to know which port to used. - */ - - len = OF_getencprop(node, "pinctrl-0", prop, sizeof(prop)); - - if ((len / sizeof(prop[0])) != 1 || prop[0] == 0) { - device_printf(dev, "missing pinctrl-0 attribute in FDT\n"); - return (ENXIO); - } - - len = OF_getprop_alloc(OF_node_from_xref(prop[0]), "amlogic,function", - (void **)&function_name); - - if (len < 0) { - device_printf(dev, - "missing amlogic,function attribute in FDT\n"); - return (ENXIO); - } - - if (strncmp("sdio-a", function_name, len) == 0) - sc->port = AML_MMC_MULT_CONFIG_PORT_A; - else if (strncmp("sdio-b", function_name, len) == 0) - sc->port = AML_MMC_MULT_CONFIG_PORT_B; - else if (strncmp("sdio-c", function_name, len) == 0) - sc->port = AML_MMC_MULT_CONFIG_PORT_C; - else { - device_printf(dev, "unknown function attribute %.*s in FDT\n", - len, function_name); - OF_prop_free(function_name); - return (ENXIO); - } - - OF_prop_free(function_name); - - sc->pwr_en.dev = NULL; - - len = OF_getencprop(node, "mmc-pwr-en", prop, sizeof(prop)); - if (len > 0) { - if ((len / sizeof(prop[0])) == 3) { - sc->pwr_en.dev = OF_device_from_xref(prop[0]); - sc->pwr_en.pin = prop[1]; - sc->pwr_en.pol = prop[2]; - } - - if (sc->pwr_en.dev == NULL) { - device_printf(dev, - "unable to process mmc-pwr-en attribute in FDT\n"); - return (ENXIO); - } - - /* Turn off power and then configure the output driver. */ - if (aml8726_mmc_power_off(sc) != 0 || - GPIO_PIN_SETFLAGS(sc->pwr_en.dev, sc->pwr_en.pin, - GPIO_PIN_OUTPUT) != 0) { - device_printf(dev, - "could not use gpio to control power\n"); - return (ENXIO); - } - } - - len = OF_getprop_alloc(node, "mmc-voltages", - (void **)&voltages); - - if (len < 0) { - device_printf(dev, "missing mmc-voltages attribute in FDT\n"); - return (ENXIO); - } - - sc->voltages[0] = 0; - sc->voltages[1] = 0; - - voltage = voltages; - nvoltages = 0; - - while (len && nvoltages < 2) { - if (strncmp("1.8", voltage, len) == 0) - sc->voltages[nvoltages] = MMC_OCR_LOW_VOLTAGE; - else if (strncmp("3.3", voltage, len) == 0) - sc->voltages[nvoltages] = MMC_OCR_320_330 | - MMC_OCR_330_340; - else { - device_printf(dev, - "unknown voltage attribute %.*s in FDT\n", - len, voltage); - OF_prop_free(voltages); - return (ENXIO); - } - - nvoltages++; - - /* queue up next string */ - while (*voltage && len) { - voltage++; - len--; - } - if (len) { - voltage++; - len--; - } - } - - OF_prop_free(voltages); - - sc->vselect.dev = NULL; - - len = OF_getencprop(node, "mmc-vselect", prop, sizeof(prop)); - if (len > 0) { - if ((len / sizeof(prop[0])) == 2) { - sc->vselect.dev = OF_device_from_xref(prop[0]); - sc->vselect.pin = prop[1]; - sc->vselect.pol = 1; - } - - if (sc->vselect.dev == NULL) { - device_printf(dev, - "unable to process mmc-vselect attribute in FDT\n"); - return (ENXIO); - } - - /* - * With the power off select voltage 0 and then - * configure the output driver. - */ - if (GPIO_PIN_SET(sc->vselect.dev, sc->vselect.pin, 0) != 0 || - GPIO_PIN_SETFLAGS(sc->vselect.dev, sc->vselect.pin, - GPIO_PIN_OUTPUT) != 0) { - device_printf(dev, - "could not use gpio to set voltage\n"); - return (ENXIO); - } - } - - if (nvoltages == 0) { - device_printf(dev, "no voltages in FDT\n"); - return (ENXIO); - } else if (nvoltages == 1 && sc->vselect.dev != NULL) { - device_printf(dev, "only one voltage in FDT\n"); - return (ENXIO); - } else if (nvoltages == 2 && sc->vselect.dev == NULL) { - device_printf(dev, "too many voltages in FDT\n"); - return (ENXIO); - } - - if (bus_alloc_resources(dev, aml8726_mmc_spec, sc->res)) { - device_printf(dev, "could not allocate resources for device\n"); - return (ENXIO); - } - - AML_MMC_LOCK_INIT(sc); - - error = bus_dma_tag_create(bus_get_dma_tag(dev), AML_MMC_ALIGN_DMA, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - AML_MMC_MAX_DMA, 1, AML_MMC_MAX_DMA, 0, NULL, NULL, &sc->dmatag); - if (error) - goto fail; - - error = bus_dmamap_create(sc->dmatag, 0, &sc->dmamap); - - if (error) - goto fail; - - error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE, - NULL, aml8726_mmc_intr, sc, &sc->ih_cookie); - if (error) { - device_printf(dev, "could not setup interrupt handler\n"); - goto fail; - } - - callout_init_mtx(&sc->ch, &sc->mtx, CALLOUT_RETURNUNLOCKED); - - sc->host.f_min = aml8726_mmc_freq(sc, aml8726_mmc_div(sc, 200000)); - sc->host.f_max = aml8726_mmc_freq(sc, aml8726_mmc_div(sc, 50000000)); - sc->host.host_ocr = sc->voltages[0] | sc->voltages[1]; - sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_HSPEED; - - child = device_add_child(dev, "mmc", -1); - - if (!child) { - device_printf(dev, "could not add mmc\n"); - error = ENXIO; - goto fail; - } - - error = device_probe_and_attach(child); - - if (error) { - device_printf(dev, "could not attach mmc\n"); - goto fail; - } - - return (0); - -fail: - if (sc->ih_cookie) - bus_teardown_intr(dev, sc->res[1], sc->ih_cookie); - - if (sc->dmamap) - bus_dmamap_destroy(sc->dmatag, sc->dmamap); - - if (sc->dmatag) - bus_dma_tag_destroy(sc->dmatag); - - AML_MMC_LOCK_DESTROY(sc); - - aml8726_mmc_power_off(sc); - - bus_release_resources(dev, aml8726_mmc_spec, sc->res); - - return (error); -} - -static int -aml8726_mmc_detach(device_t dev) -{ - struct aml8726_mmc_softc *sc = device_get_softc(dev); - - AML_MMC_LOCK(sc); - - if (sc->cmd != NULL) { - AML_MMC_UNLOCK(sc); - return (EBUSY); - } - - /* - * Turn off the power, reset the hardware state machine, - * disable the interrupts, and clear the interrupts. - */ - (void)aml8726_mmc_power_off(sc); - aml8726_mmc_soft_reset(sc, false); - CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ); - - /* This should be a NOP since no command was in flight. */ - callout_stop(&sc->ch); - - AML_MMC_UNLOCK(sc); - - bus_generic_detach(dev); - - bus_teardown_intr(dev, sc->res[1], sc->ih_cookie); - - bus_dmamap_destroy(sc->dmatag, sc->dmamap); - - bus_dma_tag_destroy(sc->dmatag); - - AML_MMC_LOCK_DESTROY(sc); - - bus_release_resources(dev, aml8726_mmc_spec, sc->res); - - return (0); -} - -static int -aml8726_mmc_shutdown(device_t dev) -{ - struct aml8726_mmc_softc *sc = device_get_softc(dev); - - /* - * Turn off the power, reset the hardware state machine, - * disable the interrupts, and clear the interrupts. - */ - (void)aml8726_mmc_power_off(sc); - aml8726_mmc_soft_reset(sc, false); - CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ); - - return (0); -} - -static int -aml8726_mmc_update_ios(device_t bus, device_t child) -{ - struct aml8726_mmc_softc *sc = device_get_softc(bus); - struct mmc_ios *ios = &sc->host.ios; - int error; - int i; - uint32_t cfgr; - - cfgr = (2 << AML_MMC_CONFIG_WR_CRC_STAT_SHIFT) | - (2 << AML_MMC_CONFIG_WR_DELAY_SHIFT) | - AML_MMC_CONFIG_DMA_ENDIAN_SBW | - (39 << AML_MMC_CONFIG_CMD_ARG_BITS_SHIFT); - - switch (ios->bus_width) { - case bus_width_4: - cfgr |= AML_MMC_CONFIG_BUS_WIDTH_4; - break; - case bus_width_1: - cfgr |= AML_MMC_CONFIG_BUS_WIDTH_1; - break; - default: - return (EINVAL); - } - - cfgr |= aml8726_mmc_div(sc, ios->clock) << - AML_MMC_CONFIG_CMD_CLK_DIV_SHIFT; - - CSR_WRITE_4(sc, AML_MMC_CONFIG_REG, cfgr); - - error = 0; - - switch (ios->power_mode) { - case power_up: - /* - * Configure and power on the regulator so that the - * voltage stabilizes prior to powering on the card. - */ - if (sc->vselect.dev != NULL) { - for (i = 0; i < 2; i++) - if ((sc->voltages[i] & (1 << ios->vdd)) != 0) - break; - if (i >= 2) - return (EINVAL); - error = GPIO_PIN_SET(sc->vselect.dev, - sc->vselect.pin, i); - } - break; - case power_on: - error = aml8726_mmc_power_on(sc); - break; - case power_off: - error = aml8726_mmc_power_off(sc); - break; - default: - return (EINVAL); - } - - return (error); -} - -static int -aml8726_mmc_request(device_t bus, device_t child, struct mmc_request *req) -{ - struct aml8726_mmc_softc *sc = device_get_softc(bus); - int mmc_error; - - AML_MMC_LOCK(sc); - - if (sc->cmd != NULL) { - AML_MMC_UNLOCK(sc); - return (EBUSY); - } - - mmc_error = aml8726_mmc_start_command(sc, req->cmd); - - AML_MMC_UNLOCK(sc); - - /* Execute the callback after dropping the lock. */ - if (mmc_error != MMC_ERR_NONE) { - req->cmd->error = mmc_error; - req->done(req); - } - - return (0); -} - -static int -aml8726_mmc_read_ivar(device_t bus, device_t child, - int which, uintptr_t *result) -{ - struct aml8726_mmc_softc *sc = device_get_softc(bus); - - switch (which) { - case MMCBR_IVAR_BUS_MODE: - *(int *)result = sc->host.ios.bus_mode; - break; - case MMCBR_IVAR_BUS_WIDTH: - *(int *)result = sc->host.ios.bus_width; - break; - case MMCBR_IVAR_CHIP_SELECT: - *(int *)result = sc->host.ios.chip_select; - break; - case MMCBR_IVAR_CLOCK: - *(int *)result = sc->host.ios.clock; - break; - case MMCBR_IVAR_F_MIN: - *(int *)result = sc->host.f_min; - break; - case MMCBR_IVAR_F_MAX: - *(int *)result = sc->host.f_max; - break; - case MMCBR_IVAR_HOST_OCR: - *(int *)result = sc->host.host_ocr; - break; - case MMCBR_IVAR_MODE: - *(int *)result = sc->host.mode; - break; - case MMCBR_IVAR_OCR: - *(int *)result = sc->host.ocr; - break; - case MMCBR_IVAR_POWER_MODE: - *(int *)result = sc->host.ios.power_mode; - break; - case MMCBR_IVAR_RETUNE_REQ: - *(int *)result = return_req_none; - case MMCBR_IVAR_VDD: - *(int *)result = sc->host.ios.vdd; - break; - case MMCBR_IVAR_VCCQ: - *result = sc->sc_host.ios.vccq; - break; - case MMCBR_IVAR_CAPS: - *(int *)result = sc->host.caps; - break; - case MMCBR_IVAR_TIMING: - *(int *)result = sc->sc_host.ios.timing; - break; - case MMCBR_IVAR_MAX_DATA: - *(int *)result = AML_MMC_MAX_DMA / MMC_SECTOR_SIZE; - break; - case MMCBR_IVAR_MAX_BUSY_TIMEOUT: - *(int *)result = 1000000; /* 1s max */ - break; - default: - return (EINVAL); - } - - return (0); -} - -static int -aml8726_mmc_write_ivar(device_t bus, device_t child, - int which, uintptr_t value) -{ - struct aml8726_mmc_softc *sc = device_get_softc(bus); - - switch (which) { - case MMCBR_IVAR_BUS_MODE: - sc->host.ios.bus_mode = value; - break; - case MMCBR_IVAR_BUS_WIDTH: - sc->host.ios.bus_width = value; - break; - case MMCBR_IVAR_CHIP_SELECT: - sc->host.ios.chip_select = value; - break; - case MMCBR_IVAR_CLOCK: - sc->host.ios.clock = value; - break; - case MMCBR_IVAR_MODE: - sc->host.mode = value; - break; - case MMCBR_IVAR_OCR: - sc->host.ocr = value; - break; - case MMCBR_IVAR_POWER_MODE: - sc->host.ios.power_mode = value; - break; - case MMCBR_IVAR_VDD: - sc->host.ios.vdd = value; - break; - case MMCBR_IVAR_VCCQ: - sc->sc_host.ios.vccq = value; - break; - case MMCBR_IVAR_TIMING: - sc->sc_host.ios.timing = value; - break; - /* These are read-only */ - case MMCBR_IVAR_CAPS: - case MMCBR_IVAR_HOST_OCR: - case MMCBR_IVAR_F_MIN: - case MMCBR_IVAR_F_MAX: - case MMCBR_IVAR_MAX_DATA: - default: - return (EINVAL); - } - - return (0); -} - -static int -aml8726_mmc_get_ro(device_t bus, device_t child) -{ - - return (0); -} - -static int -aml8726_mmc_acquire_host(device_t bus, device_t child) -{ - struct aml8726_mmc_softc *sc = device_get_softc(bus); - - AML_MMC_LOCK(sc); - - while (sc->bus_busy) - mtx_sleep(sc, &sc->mtx, PZERO, "mmc", hz / 5); - sc->bus_busy++; - - AML_MMC_UNLOCK(sc); - - return (0); -} - -static int -aml8726_mmc_release_host(device_t bus, device_t child) -{ - struct aml8726_mmc_softc *sc = device_get_softc(bus); - - AML_MMC_LOCK(sc); - - sc->bus_busy--; - wakeup(sc); - - AML_MMC_UNLOCK(sc); - - return (0); -} - -static device_method_t aml8726_mmc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_mmc_probe), - DEVMETHOD(device_attach, aml8726_mmc_attach), - DEVMETHOD(device_detach, aml8726_mmc_detach), - DEVMETHOD(device_shutdown, aml8726_mmc_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_read_ivar, aml8726_mmc_read_ivar), - DEVMETHOD(bus_write_ivar, aml8726_mmc_write_ivar), - - /* MMC bridge interface */ - DEVMETHOD(mmcbr_update_ios, aml8726_mmc_update_ios), - DEVMETHOD(mmcbr_request, aml8726_mmc_request), - DEVMETHOD(mmcbr_get_ro, aml8726_mmc_get_ro), - DEVMETHOD(mmcbr_acquire_host, aml8726_mmc_acquire_host), - DEVMETHOD(mmcbr_release_host, aml8726_mmc_release_host), - - DEVMETHOD_END -}; - -static driver_t aml8726_mmc_driver = { - "aml8726_mmc", - aml8726_mmc_methods, - sizeof(struct aml8726_mmc_softc), -}; - -static devclass_t aml8726_mmc_devclass; - -DRIVER_MODULE(aml8726_mmc, simplebus, aml8726_mmc_driver, - aml8726_mmc_devclass, NULL, NULL); -MODULE_DEPEND(aml8726_mmc, aml8726_gpio, 1, 1, 1); -MMC_DECLARE_BRIDGE(aml8726_mmc); Index: head/sys/arm/amlogic/aml8726/aml8726_mp.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_mp.c +++ head/sys/arm/amlogic/aml8726/aml8726_mp.c @@ -1,625 +0,0 @@ -/*- - * Copyright 2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 multiprocessor support. - * - * Some processors require powering on which involves poking registers - * on the aobus and cbus ... it's expected that these locations are set - * in stone. - * - * Locking is not used as these routines should only be called by the BP - * during startup and should complete prior to the APs being released (the - * issue being to ensure that a register such as AML_SOC_CPU_CLK_CNTL_REG - * is not concurrently modified). - */ - -#include -__FBSDID("$FreeBSD$"); -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -static const char *scu_compatible[] = { - "arm,cortex-a5-scu", - "arm,cortex-a9-scu", - NULL -}; - -static const char *scu_errata_764369[] = { - "arm,cortex-a9-scu", - NULL -}; - -static const char *cpucfg_compatible[] = { - "amlogic,aml8726-cpuconfig", - NULL -}; - -static struct { - boolean_t errata_764369; - u_long scu_size; - struct resource scu_res; - u_long cpucfg_size; - struct resource cpucfg_res; - struct resource aobus_res; - struct resource cbus_res; -} aml8726_smp; - -#define AML_SCU_CONTROL_REG 0 -#define AML_SCU_CONTROL_ENABLE 1 -#define AML_SCU_CONFIG_REG 4 -#define AML_SCU_CONFIG_NCPU_MASK 0x3 -#define AML_SCU_CPU_PWR_STATUS_REG 8 -#define AML_SCU_CPU_PWR_STATUS_CPU3_MASK (3 << 24) -#define AML_SCU_CPU_PWR_STATUS_CPU2_MASK (3 << 16) -#define AML_SCU_CPU_PWR_STATUS_CPU1_MASK (3 << 8) -#define AML_SCU_CPU_PWR_STATUS_CPU0_MASK 3 -#define AML_SCU_INV_TAGS_REG 12 -#define AML_SCU_DIAG_CONTROL_REG 48 -#define AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT 1 - -#define AML_CPUCONF_CONTROL_REG 0 -#define AML_CPUCONF_CPU1_ADDR_REG 4 -#define AML_CPUCONF_CPU2_ADDR_REG 8 -#define AML_CPUCONF_CPU3_ADDR_REG 12 - -/* aobus */ - -#define AML_M8_CPU_PWR_CNTL0_REG 0xe0 -#define AML_M8B_CPU_PWR_CNTL0_MODE_CPU3_MASK (3 << 22) -#define AML_M8B_CPU_PWR_CNTL0_MODE_CPU2_MASK (3 << 20) -#define AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK (3 << 18) - -#define AML_M8_CPU_PWR_CNTL0_ISO_CPU3 (1 << 3) -#define AML_M8_CPU_PWR_CNTL0_ISO_CPU2 (1 << 2) -#define AML_M8_CPU_PWR_CNTL0_ISO_CPU1 (1 << 1) - -#define AML_M8_CPU_PWR_CNTL1_REG 0xe4 -#define AML_M8B_CPU_PWR_CNTL1_PWR_CPU3 (1 << 19) -#define AML_M8B_CPU_PWR_CNTL1_PWR_CPU2 (1 << 18) -#define AML_M8B_CPU_PWR_CNTL1_PWR_CPU1 (1 << 17) - -#define AML_M8_CPU_PWR_CNTL1_MODE_CPU3_MASK (3 << 8) -#define AML_M8_CPU_PWR_CNTL1_MODE_CPU2_MASK (3 << 6) -#define AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK (3 << 4) - -#define AML_M8B_CPU_PWR_MEM_PD0_REG 0xf4 -#define AML_M8B_CPU_PWR_MEM_PD0_CPU3 (0xf << 20) -#define AML_M8B_CPU_PWR_MEM_PD0_CPU2 (0xf << 24) -#define AML_M8B_CPU_PWR_MEM_PD0_CPU1 (0xf << 28) - -/* cbus */ - -#define AML_SOC_CPU_CLK_CNTL_REG 0x419c -#define AML_M8_CPU_CLK_CNTL_RESET_CPU3 (1 << 27) -#define AML_M8_CPU_CLK_CNTL_RESET_CPU2 (1 << 26) -#define AML_M8_CPU_CLK_CNTL_RESET_CPU1 (1 << 25) - -#define SCU_WRITE_4(reg, value) bus_write_4(&aml8726_smp.scu_res, \ - (reg), (value)) -#define SCU_READ_4(reg) bus_read_4(&aml8726_smp.scu_res, (reg)) -#define SCU_BARRIER(reg) bus_barrier(&aml8726_smp.scu_res, \ - (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -#define CPUCONF_WRITE_4(reg, value) bus_write_4(&aml8726_smp.cpucfg_res, \ - (reg), (value)) -#define CPUCONF_READ_4(reg) bus_read_4(&aml8726_smp.cpucfg_res, \ - (reg)) -#define CPUCONF_BARRIER(reg) bus_barrier(&aml8726_smp.cpucfg_res, \ - (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -#define AOBUS_WRITE_4(reg, value) bus_write_4(&aml8726_smp.aobus_res, \ - (reg), (value)) -#define AOBUS_READ_4(reg) bus_read_4(&aml8726_smp.aobus_res, \ - (reg)) -#define AOBUS_BARRIER(reg) bus_barrier(&aml8726_smp.aobus_res, \ - (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -#define CBUS_WRITE_4(reg, value) bus_write_4(&aml8726_smp.cbus_res, \ - (reg), (value)) -#define CBUS_READ_4(reg) bus_read_4(&aml8726_smp.cbus_res, \ - (reg)) -#define CBUS_BARRIER(reg) bus_barrier(&aml8726_smp.cbus_res, \ - (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -static phandle_t -find_node_for_device(const char *device, const char **compatible) -{ - int i; - phandle_t node; - - /* - * Try to access the node directly i.e. through /aliases/. - */ - - if ((node = OF_finddevice(device)) != -1) - for (i = 0; compatible[i]; i++) - if (fdt_is_compatible_strict(node, compatible[i])) - return node; - - /* - * Find the node the long way. - */ - - for (i = 0; compatible[i]; i++) { - if ((node = OF_finddevice("/soc")) == -1) - return (0); - - if ((node = fdt_find_compatible(node, compatible[i], 1)) != 0) - return node; - } - - return (0); -} - -static int -alloc_resource_for_node(phandle_t node, struct resource *res, u_long *size) -{ - int err; - u_long pbase, psize; - u_long start; - - if ((err = fdt_get_range(OF_parent(node), 0, &pbase, &psize)) != 0 || - (err = fdt_regsize(node, &start, size)) != 0) - return (err); - - start += pbase; - - memset(res, 0, sizeof(*res)); - - res->r_bustag = fdtbus_bs_tag; - - err = bus_space_map(res->r_bustag, start, *size, 0, &res->r_bushandle); - - return (err); -} - -static void -power_on_cpu(int cpu) -{ - uint32_t scpsr; - uint32_t value; - - if (cpu <= 0) - return; - - /* - * Power on the CPU if the intricate details are known, otherwise - * just hope for the best (it may have already be powered on by - * the hardware / firmware). - */ - - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M8: - case AML_SOC_HW_REV_M8B: - /* - * Set the SCU power status for the CPU to normal mode. - */ - scpsr = SCU_READ_4(AML_SCU_CPU_PWR_STATUS_REG); - scpsr &= ~(AML_SCU_CPU_PWR_STATUS_CPU1_MASK << ((cpu - 1) * 8)); - SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr); - SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG); - - if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { - /* - * Reset may cause the current power status from the - * actual CPU to be written to the SCU (over-writing - * the value we've just written) so set it to normal - * mode as well. - */ - value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG); - value &= ~(AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK << - ((cpu - 1) * 2)); - AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value); - AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG); - } - - DELAY(5); - - /* - * Assert reset. - */ - value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG); - value |= AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1); - CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value); - CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG); - - if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { - /* - * Release RAM pull-down. - */ - value = AOBUS_READ_4(AML_M8B_CPU_PWR_MEM_PD0_REG); - value &= ~((uint32_t)AML_M8B_CPU_PWR_MEM_PD0_CPU1 >> - ((cpu - 1) * 4)); - AOBUS_WRITE_4(AML_M8B_CPU_PWR_MEM_PD0_REG, value); - AOBUS_BARRIER(AML_M8B_CPU_PWR_MEM_PD0_REG); - } - - /* - * Power on CPU. - */ - value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG); - value &= ~(AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK << - ((cpu - 1) * 2)); - AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL1_REG, value); - AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL1_REG); - - DELAY(10); - - if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { - /* - * Wait for power on confirmation. - */ - for ( ; ; ) { - value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG); - value &= AML_M8B_CPU_PWR_CNTL1_PWR_CPU1 << - (cpu - 1); - if (value) - break; - DELAY(10); - } - } - - /* - * Release peripheral clamp. - */ - value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG); - value &= ~(AML_M8_CPU_PWR_CNTL0_ISO_CPU1 << (cpu - 1)); - AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value); - AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG); - - /* - * Release reset. - */ - value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG); - value &= ~(AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1)); - CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value); - CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG); - - if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { - /* - * The Amlogic Linux platform code sets the SCU power - * status for the CPU again for some reason so we - * follow suit (perhaps in case the reset caused - * a stale power status from the actual CPU to be - * written to the SCU). - */ - SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr); - SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG); - } - break; - default: - break; - } -} - -void -platform_mp_setmaxid(void) -{ - int err; - int i; - int ncpu; - phandle_t cpucfg_node; - phandle_t scu_node; - uint32_t value; - - if (mp_ncpus != 0) - return; - - ncpu = 1; - - /* - * Is the hardware necessary for SMP present? - */ - - if ((scu_node = find_node_for_device("scu", scu_compatible)) == 0) - goto moveon; - - if ((cpucfg_node = find_node_for_device("cpuconfig", - cpucfg_compatible)) == 0) - goto moveon; - - if (alloc_resource_for_node(scu_node, &aml8726_smp.scu_res, - &aml8726_smp.scu_size) != 0) - panic("Could not allocate resource for SCU"); - - if (alloc_resource_for_node(cpucfg_node, &aml8726_smp.cpucfg_res, - &aml8726_smp.cpucfg_size) != 0) - panic("Could not allocate resource for CPUCONFIG"); - - /* - * Strictly speaking the aobus and cbus may not be required in - * order to start an AP (it depends on the processor), however - * always mapping them in simplifies the code. - */ - - aml8726_smp.aobus_res.r_bustag = fdtbus_bs_tag; - - err = bus_space_map(aml8726_smp.aobus_res.r_bustag, - AML_SOC_AOBUS_BASE_ADDR, 0x100000, - 0, &aml8726_smp.aobus_res.r_bushandle); - - if (err) - panic("Could not allocate resource for AOBUS"); - - aml8726_smp.cbus_res.r_bustag = fdtbus_bs_tag; - - err = bus_space_map(aml8726_smp.cbus_res.r_bustag, - AML_SOC_CBUS_BASE_ADDR, 0x100000, - 0, &aml8726_smp.cbus_res.r_bushandle); - - if (err) - panic("Could not allocate resource for CBUS"); - - aml8726_smp.errata_764369 = false; - for (i = 0; scu_errata_764369[i]; i++) - if (fdt_is_compatible_strict(scu_node, scu_errata_764369[i])) { - aml8726_smp.errata_764369 = true; - break; - } - - /* - * Read the number of CPUs present. - */ - value = SCU_READ_4(AML_SCU_CONFIG_REG); - ncpu = (value & AML_SCU_CONFIG_NCPU_MASK) + 1; - -moveon: - mp_ncpus = ncpu; - mp_maxid = ncpu - 1; -} - -void -platform_mp_start_ap(void) -{ - int i; - uint32_t reg; - uint32_t value; - vm_paddr_t paddr; - - if (mp_ncpus < 2) - return; - - /* - * Invalidate SCU cache tags. The 0x0000ffff constant invalidates - * all ways on all cores 0-3. Per the ARM docs, it's harmless to - * write to the bits for cores that are not present. - */ - SCU_WRITE_4(AML_SCU_INV_TAGS_REG, 0x0000ffff); - - if (aml8726_smp.errata_764369) { - /* - * Erratum ARM/MP: 764369 (problems with cache maintenance). - * Setting the "disable-migratory bit" in the undocumented SCU - * Diagnostic Control Register helps work around the problem. - */ - value = SCU_READ_4(AML_SCU_DIAG_CONTROL_REG); - value |= AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT; - SCU_WRITE_4(AML_SCU_DIAG_CONTROL_REG, value); - } - - /* - * Enable the SCU, then clean the cache on this core. After these - * two operations the cache tag ram in the SCU is coherent with - * the contents of the cache on this core. The other cores aren't - * running yet so their caches can't contain valid data yet, however - * we've initialized their SCU tag ram above, so they will be - * coherent from startup. - */ - value = SCU_READ_4(AML_SCU_CONTROL_REG); - value |= AML_SCU_CONTROL_ENABLE; - SCU_WRITE_4(AML_SCU_CONTROL_REG, value); - SCU_BARRIER(AML_SCU_CONTROL_REG); - dcache_wbinv_poc_all(); - - /* Set the boot address and power on each AP. */ - paddr = pmap_kextract((vm_offset_t)mpentry); - for (i = 1; i < mp_ncpus; i++) { - reg = AML_CPUCONF_CPU1_ADDR_REG + ((i - 1) * 4); - CPUCONF_WRITE_4(reg, paddr); - CPUCONF_BARRIER(reg); - - power_on_cpu(i); - } - - /* - * Enable the APs. - * - * The Amlogic Linux platform code sets the lsb for some reason - * in addition to the enable bit for each AP so we follow suit - * (the lsb may be the enable bit for the BP, though in that case - * it should already be set since it's currently running). - */ - value = CPUCONF_READ_4(AML_CPUCONF_CONTROL_REG); - value |= 1; - for (i = 1; i < mp_ncpus; i++) - value |= (1 << i); - CPUCONF_WRITE_4(AML_CPUCONF_CONTROL_REG, value); - CPUCONF_BARRIER(AML_CPUCONF_CONTROL_REG); - - /* Wakeup the now enabled APs */ - dsb(); - sev(); - - /* - * Free the resources which are not needed after startup. - */ - bus_space_unmap(aml8726_smp.scu_res.r_bustag, - aml8726_smp.scu_res.r_bushandle, - aml8726_smp.scu_size); - bus_space_unmap(aml8726_smp.cpucfg_res.r_bustag, - aml8726_smp.cpucfg_res.r_bushandle, - aml8726_smp.cpucfg_size); - bus_space_unmap(aml8726_smp.aobus_res.r_bustag, - aml8726_smp.aobus_res.r_bushandle, - 0x100000); - bus_space_unmap(aml8726_smp.cbus_res.r_bustag, - aml8726_smp.cbus_res.r_bushandle, - 0x100000); - memset(&aml8726_smp, 0, sizeof(aml8726_smp)); -} - -/* - * Stub drivers for cosmetic purposes. - */ -struct aml8726_scu_softc { - device_t dev; -}; - -static int -aml8726_scu_probe(device_t dev) -{ - int i; - - for (i = 0; scu_compatible[i]; i++) - if (ofw_bus_is_compatible(dev, scu_compatible[i])) - break; - - if (!scu_compatible[i]) - return (ENXIO); - - device_set_desc(dev, "ARM Snoop Control Unit"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_scu_attach(device_t dev) -{ - struct aml8726_scu_softc *sc = device_get_softc(dev); - - sc->dev = dev; - - return (0); -} - -static int -aml8726_scu_detach(device_t dev) -{ - - return (0); -} - -static device_method_t aml8726_scu_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_scu_probe), - DEVMETHOD(device_attach, aml8726_scu_attach), - DEVMETHOD(device_detach, aml8726_scu_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_scu_driver = { - "scu", - aml8726_scu_methods, - sizeof(struct aml8726_scu_softc), -}; - -static devclass_t aml8726_scu_devclass; - -EARLY_DRIVER_MODULE(scu, simplebus, aml8726_scu_driver, aml8726_scu_devclass, - 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE); - -struct aml8726_cpucfg_softc { - device_t dev; -}; - -static int -aml8726_cpucfg_probe(device_t dev) -{ - int i; - - for (i = 0; cpucfg_compatible[i]; i++) - if (ofw_bus_is_compatible(dev, cpucfg_compatible[i])) - break; - - if (!cpucfg_compatible[i]) - return (ENXIO); - - device_set_desc(dev, "Amlogic CPU Config"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_cpucfg_attach(device_t dev) -{ - struct aml8726_cpucfg_softc *sc = device_get_softc(dev); - - sc->dev = dev; - - return (0); -} - -static int -aml8726_cpucfg_detach(device_t dev) -{ - - return (0); -} - -static device_method_t aml8726_cpucfg_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_cpucfg_probe), - DEVMETHOD(device_attach, aml8726_cpucfg_attach), - DEVMETHOD(device_detach, aml8726_cpucfg_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_cpucfg_driver = { - "cpuconfig", - aml8726_cpucfg_methods, - sizeof(struct aml8726_cpucfg_softc), -}; - -static devclass_t aml8726_cpucfg_devclass; - -EARLY_DRIVER_MODULE(cpuconfig, simplebus, aml8726_cpucfg_driver, - aml8726_cpucfg_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE); Index: head/sys/arm/amlogic/aml8726/aml8726_pic.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_pic.c +++ head/sys/arm/amlogic/aml8726/aml8726_pic.c @@ -1,277 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 PIC driver. - * - * The current implementation doesn't include support for FIQ. - * - * There is a set of four interrupt controllers per cpu located in adjacent - * memory addresses (the set for cpu 1 starts right after the set for cpu 0) - * ... this allows for interrupt handling to be spread across the cpus. - * - * The multicore chips also have a GIC ... typically they run SMP kernels - * which include the GIC driver in which case this driver is simply used - * to disable the PIC. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -struct aml8726_pic_softc { - device_t dev; - struct resource * res[1]; -}; - -static struct resource_spec aml8726_pic_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, 0 } -}; - -/* - * devclass_get_device / device_get_softc could be used - * to dynamically locate this, however the pic is a - * required device which can't be unloaded so there's - * no need for the overhead. - */ -static struct aml8726_pic_softc *aml8726_pic_sc = NULL; - -#define AML_PIC_NCNTRLS 4 -#define AML_PIC_IRQS_PER_CNTRL 32 - -#define AML_PIC_NIRQS (AML_PIC_NCNTRLS * AML_PIC_IRQS_PER_CNTRL) - -#define AML_PIC_0_STAT_REG 0 -#define AML_PIC_0_STAT_CLR_REG 4 -#define AML_PIC_0_MASK_REG 8 -#define AML_PIC_0_FIRQ_SEL 12 - -#define AML_PIC_1_STAT_REG 16 -#define AML_PIC_1_STAT_CLR_REG 20 -#define AML_PIC_1_MASK_REG 24 -#define AML_PIC_1_FIRQ_SEL 28 - -#define AML_PIC_2_STAT_REG 32 -#define AML_PIC_2_STAT_CLR_REG 36 -#define AML_PIC_2_MASK_REG 40 -#define AML_PIC_2_FIRQ_SEL 44 - -#define AML_PIC_3_STAT_REG 48 -#define AML_PIC_3_STAT_CLR_REG 52 -#define AML_PIC_3_MASK_REG 56 -#define AML_PIC_3_FIRQ_SEL 60 - -#define AML_PIC_CTRL(x) ((x) >> 5) -#define AML_PIC_BIT(x) (1 << ((x) & 0x1f)) - -#define AML_PIC_STAT_REG(x) (AML_PIC_0_STAT_REG + AML_PIC_CTRL(x) * 16) -#define AML_PIC_STAT_CLR_REG(x) (AML_PIC_0_STAT_CLR_REG + AML_PIC_CTRL(x) * 16) -#define AML_PIC_MASK_REG(x) (AML_PIC_0_MASK_REG + AML_PIC_CTRL(x) * 16) -#define AML_PIC_FIRQ_SEL(x) (AML_PIC_0_FIRQ_REG + AML_PIC_CTRL(x) * 16) - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) -#define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ - (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -static void -aml8726_pic_eoi(void *arg) -{ - uintptr_t nb = (uintptr_t) arg; - - if (nb >= AML_PIC_NIRQS) - return; - - arm_irq_memory_barrier(nb); - - CSR_WRITE_4(aml8726_pic_sc, AML_PIC_STAT_CLR_REG(nb), AML_PIC_BIT(nb)); - - CSR_BARRIER(aml8726_pic_sc, AML_PIC_STAT_CLR_REG(nb)); -} - -static int -aml8726_pic_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-pic")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 PIC"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_pic_attach(device_t dev) -{ - struct aml8726_pic_softc *sc = device_get_softc(dev); - int i; - - /* There should be exactly one instance. */ - if (aml8726_pic_sc != NULL) - return (ENXIO); - - sc->dev = dev; - - if (bus_alloc_resources(dev, aml8726_pic_spec, sc->res)) { - device_printf(dev, "could not allocate resources for device\n"); - return (ENXIO); - } - - /* - * Disable, clear, and set the interrupts to normal mode. - */ - for (i = 0; i < AML_PIC_NCNTRLS; i++) { - CSR_WRITE_4(sc, AML_PIC_0_MASK_REG + i * 16, 0); - CSR_WRITE_4(sc, AML_PIC_0_STAT_CLR_REG + i * 16, ~0u); - CSR_WRITE_4(sc, AML_PIC_0_FIRQ_SEL + i * 16, 0); - } - -#ifndef DEV_GIC - arm_post_filter = aml8726_pic_eoi; -#else - device_printf(dev, "disabled in favor of gic\n"); -#endif - - aml8726_pic_sc = sc; - - return (0); -} - -static int -aml8726_pic_detach(device_t dev) -{ - - return (EBUSY); -} - -static device_method_t aml8726_pic_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_pic_probe), - DEVMETHOD(device_attach, aml8726_pic_attach), - DEVMETHOD(device_detach, aml8726_pic_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_pic_driver = { - "pic", - aml8726_pic_methods, - sizeof(struct aml8726_pic_softc), -}; - -static devclass_t aml8726_pic_devclass; - -EARLY_DRIVER_MODULE(pic, simplebus, aml8726_pic_driver, aml8726_pic_devclass, - 0, 0, BUS_PASS_INTERRUPT); - -#ifndef DEV_GIC -int -arm_get_next_irq(int last) -{ - uint32_t value; - int irq; - int start; - - /* - * The extra complexity is simply so that all IRQs are checked - * round robin so a particularly busy interrupt can't prevent - * other interrupts from being serviced. - */ - - start = (last + 1) % AML_PIC_NIRQS; - irq = start; - - for ( ; ; ) { - value = CSR_READ_4(aml8726_pic_sc, AML_PIC_STAT_REG(irq)); - - for ( ; ; ) { - if ((value & AML_PIC_BIT(irq)) != 0) - return (irq); - - irq = (irq + 1) % AML_PIC_NIRQS; - - if (irq == start) - return (-1); - - if ((irq % AML_PIC_IRQS_PER_CNTRL) == 0) - break; - } - } -} - -void -arm_mask_irq(uintptr_t nb) -{ - uint32_t mask; - - if (nb >= AML_PIC_NIRQS) - return; - - mask = CSR_READ_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb)); - mask &= ~AML_PIC_BIT(nb); - CSR_WRITE_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb), mask); - - CSR_BARRIER(aml8726_pic_sc, AML_PIC_MASK_REG(nb)); - - aml8726_pic_eoi((void *)nb); -} - -void -arm_unmask_irq(uintptr_t nb) -{ - uint32_t mask; - - if (nb >= AML_PIC_NIRQS) - return; - - arm_irq_memory_barrier(nb); - - mask = CSR_READ_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb)); - mask |= AML_PIC_BIT(nb); - CSR_WRITE_4(aml8726_pic_sc, AML_PIC_MASK_REG(nb), mask); - - CSR_BARRIER(aml8726_pic_sc, AML_PIC_MASK_REG(nb)); -} -#endif Index: head/sys/arm/amlogic/aml8726/aml8726_pinctrl.h =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_pinctrl.h +++ head/sys/arm/amlogic/aml8726/aml8726_pinctrl.h @@ -1,1082 +0,0 @@ -/*- - * Copyright 2015 John Wehle - * 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$ - */ - -/* - * In addition to supplying entries for pins which need to be configured - * by the operating system it's also necessary to supply entries for pins - * which may have been configured by the firmware for a different purpose. - */ - -#ifndef _ARM_AMLOGIC_AML8726_PINCTRL_H -#define _ARM_AMLOGIC_AML8726_PINCTRL_H - -enum aml8726_pinctrl_pull_mode { - aml8726_unknown_pm, - aml8726_disable_pm, - aml8726_enable_pm, - aml8726_enable_down_pm, - aml8726_enable_up_pm -}; - -struct aml8726_pinctrl_pkg_pin { - const char *pkg_name; - boolean_t aobus; - uint32_t pull_addr; - uint32_t pull_bits; -}; - -struct aml8726_pinctrl_pin { - const char *name; - const char *pkg_name; - uint32_t mux_addr; - uint32_t mux_bits; -}; - -struct aml8726_pinctrl_function { - const char *name; - struct aml8726_pinctrl_pin *pins; -}; - -/* - * aml8726-m3 - * - * start size - * cbus mux 0x202c 36 - * cbus pu_pd 0x203a 24 - * cbus pull_en 0x203a 24 - * aobus mux 0x0005 4 - * aobus pu_pd 0x000b 4 - * aobus pull_en 0x000b 4 - */ - -static struct aml8726_pinctrl_pkg_pin aml8726_m3_pkg_pin[] = { - { "card_0", false, 0, 0x00000000 }, - { "card_1", false, 0, 0x00000000 }, - { "card_2", false, 0, 0x00000000 }, - { "card_3", false, 0, 0x00000000 }, - { "card_4", false, 0, 0x00000000 }, - { "card_5", false, 0, 0x00000000 }, - { "card_6", false, 0, 0x00000000 }, - - { "gpioc_10", false, 0, 0x00000000 }, - { "gpioc_11", false, 0, 0x00000000 }, - { "gpioc_12", false, 0, 0x00000000 }, - { "gpioc_13", false, 0, 0x00000000 }, - - { "gpiox_13", false, 0, 0x00000000 }, - { "gpiox_14", false, 0, 0x00000000 }, - { "gpiox_15", false, 0, 0x00000000 }, - { "gpiox_16", false, 0, 0x00000000 }, - { "gpiox_17", false, 0, 0x00000000 }, - { "gpiox_18", false, 0, 0x00000000 }, - { "gpiox_19", false, 0, 0x00000000 }, - { "gpiox_20", false, 0, 0x00000000 }, - { "gpiox_21", false, 0, 0x00000000 }, - { "gpiox_22", false, 0, 0x00000000 }, - { "gpiox_23", false, 0, 0x00000000 }, - { "gpiox_24", false, 0, 0x00000000 }, - { "gpiox_25", false, 0, 0x00000000 }, - { "gpiox_26", false, 0, 0x00000000 }, - { "gpiox_27", false, 0, 0x00000000 }, - { "gpiox_28", false, 0, 0x00000000 }, - - { "gpioy_0", false, 0, 0x00000000 }, - { "gpioy_1", false, 0, 0x00000000 }, - { "gpioy_2", false, 0, 0x00000000 }, - { "gpioy_3", false, 0, 0x00000000 }, - { "gpioy_4", false, 0, 0x00000000 }, - { "gpioy_5", false, 0, 0x00000000 }, - { "gpioy_6", false, 0, 0x00000000 }, - { "gpioy_7", false, 0, 0x00000000 }, - { "gpioy_8", false, 0, 0x00000000 }, - { "gpioy_9", false, 0, 0x00000000 }, - - { "gpioao_0", true, 0, 0x00000000 }, - { "gpioao_1", true, 0, 0x00000000 }, - { "gpioao_2", true, 0, 0x00000000 }, - { "gpioao_3", true, 0, 0x00000000 }, - { "gpioao_4", true, 0, 0x00000000 }, - { "gpioao_5", true, 0, 0x00000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_gpio[] = { - { "card_0", "card_0", 0, 0x00000000 }, - { "card_1", "card_1", 0, 0x00000000 }, - { "card_2", "card_2", 0, 0x00000000 }, - { "card_3", "card_3", 0, 0x00000000 }, - { "card_4", "card_4", 0, 0x00000000 }, - { "card_5", "card_5", 0, 0x00000000 }, - { "card_6", "card_6", 0, 0x00000000 }, - - { "gpioc_10", "gpioc_10", 0, 0x00000000 }, - { "gpioc_11", "gpioc_11", 0, 0x00000000 }, - { "gpioc_12", "gpioc_12", 0, 0x00000000 }, - { "gpioc_13", "gpioc_13", 0, 0x00000000 }, - - { "gpiox_13", "gpiox_13", 0, 0x00000000 }, - { "gpiox_14", "gpiox_14", 0, 0x00000000 }, - { "gpiox_15", "gpiox_15", 0, 0x00000000 }, - { "gpiox_16", "gpiox_16", 0, 0x00000000 }, - { "gpiox_17", "gpiox_17", 0, 0x00000000 }, - { "gpiox_18", "gpiox_18", 0, 0x00000000 }, - { "gpiox_19", "gpiox_19", 0, 0x00000000 }, - { "gpiox_20", "gpiox_20", 0, 0x00000000 }, - { "gpiox_21", "gpiox_21", 0, 0x00000000 }, - { "gpiox_22", "gpiox_22", 0, 0x00000000 }, - { "gpiox_23", "gpiox_23", 0, 0x00000000 }, - { "gpiox_24", "gpiox_24", 0, 0x00000000 }, - { "gpiox_25", "gpiox_25", 0, 0x00000000 }, - { "gpiox_26", "gpiox_26", 0, 0x00000000 }, - { "gpiox_27", "gpiox_27", 0, 0x00000000 }, - { "gpiox_28", "gpiox_28", 0, 0x00000000 }, - - { "gpioy_0", "gpioy_0", 0, 0x00000000 }, - { "gpioy_1", "gpioy_1", 0, 0x00000000 }, - { "gpioy_2", "gpioy_2", 0, 0x00000000 }, - { "gpioy_3", "gpioy_3", 0, 0x00000000 }, - { "gpioy_4", "gpioy_4", 0, 0x00000000 }, - { "gpioy_5", "gpioy_5", 0, 0x00000000 }, - { "gpioy_6", "gpioy_6", 0, 0x00000000 }, - { "gpioy_7", "gpioy_7", 0, 0x00000000 }, - { "gpioy_8", "gpioy_8", 0, 0x00000000 }, - { "gpioy_9", "gpioy_9", 0, 0x00000000 }, - - { "gpioao_0", "gpioao_0", 0, 0x00000000 }, - { "gpioao_1", "gpioao_1", 0, 0x00000000 }, - { "gpioao_2", "gpioao_2", 0, 0x00000000 }, - { "gpioao_3", "gpioao_3", 0, 0x00000000 }, - { "gpioao_4", "gpioao_4", 0, 0x00000000 }, - { "gpioao_5", "gpioao_5", 0, 0x00000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_ethernet[] = { - { "clk50_in", "gpioy_0", 24, 0x00040000 }, - { "clk_out", "gpioy_0", 24, 0x00020000 }, - { "tx_en", "gpioy_5", 24, 0x00001000 }, - { "tx_d0", "gpioy_7", 24, 0x00000400 }, - { "tx_d1", "gpioy_6", 24, 0x00000800 }, - { "crs_dv", "gpioy_2", 24, 0x00008000 }, - { "rx_err", "gpioy_1", 24, 0x00010000 }, - { "rx_d0", "gpioy_4", 24, 0x00002000 }, - { "rx_d1", "gpioy_3", 24, 0x00004000 }, - { "mdc", "gpioy_8", 24, 0x00000200 }, - { "mdio", "gpioy_9", 24, 0x00000100 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_hdmi[] = { - { "cec", "gpioc_13", 4, 0x02000000 }, - { "hpd", "gpioc_10", 4, 0x00400000 }, - { "scl", "gpioc_12", 4, 0x01000000 }, - { "sda", "gpioc_11", 4, 0x00800000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_i2c_a[] = { - { "scl", "gpiox_26", 20, 0x04000000 }, - { "sda", "gpiox_25", 20, 0x08000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_i2c_b[] = { - { "scl", "gpiox_28", 20, 0x40000000 }, - { "sda", "gpiox_27", 20, 0x80000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_sdio_b[] = { - { "clk", "card_4", 8, 0x00000800 }, - { "cmd", "card_5", 8, 0x00000400 }, - { "d0", "card_0", 8, 0x00008000 }, - { "d1", "card_1", 8, 0x00004000 }, - { "d2", "card_2", 8, 0x00002000 }, - { "d3", "card_3", 8, 0x00001000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_sdxc_b[] = { - { "clk", "card_4", 8, 0x00000020 }, - { "cmd", "card_5", 8, 0x00000010 }, - { "d0", "card_0", 8, 0x00000080 }, - { "d1", "card_1", 8, 0x00000040 }, - { "d2", "card_2", 8, 0x00000040 }, - { "d3", "card_3", 8, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_uart_a[] = { - { "tx", "gpiox_13", 16, 0x00002000 }, - { "rx", "gpiox_14", 16, 0x00001000 }, - { "cts", "gpiox_15", 16, 0x00000800 }, - { "rts", "gpiox_16", 16, 0x00000400 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_uart_b[] = { - { "tx", "gpiox_17", 16, 0x00000200 }, - { "rx", "gpiox_18", 16, 0x00000100 }, - { "cts", "gpiox_19", 16, 0x00000080 }, - { "rts", "gpiox_20", 16, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_uart_c[] = { - { "tx", "gpiox_21", 16, 0x00000008 }, - { "rx", "gpiox_22", 16, 0x00000004 }, - { "cts", "gpiox_23", 16, 0x00000002 }, - { "rts", "gpiox_24", 16, 0x00000001 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_i2c_ao[] = { - { "scl", "gpioao_4", 0, 0x00000400 }, - { "sda", "gpioao_5", 0, 0x00000200 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m3_uart_ao[] = { - { "tx", "gpioao_0", 0, 0x00001000 }, - { "rx", "gpioao_1", 0, 0x00000800 }, - { "cts", "gpioao_2", 0, 0x00000400 }, - { "rts", "gpioao_3", 0, 0x00000200 }, - { NULL } -}; - -struct aml8726_pinctrl_function aml8726_m3_pinctrl[] = { - { "gpio", aml8726_m3_gpio }, - { "ethernet", aml8726_m3_ethernet }, - { "hdmi", aml8726_m3_hdmi }, - { "i2c-a", aml8726_m3_i2c_a }, - { "i2c-b", aml8726_m3_i2c_b }, - { "sdio-b", aml8726_m3_sdio_b }, - { "sdxc-b", aml8726_m3_sdxc_b }, - { "uart-a", aml8726_m3_uart_a }, - { "uart-b", aml8726_m3_uart_b }, - { "uart-c", aml8726_m3_uart_c }, - { "i2c-ao", aml8726_m3_i2c_ao }, - { "uart-ao", aml8726_m3_uart_ao }, - { NULL } -}; - -/* - * aml8726-m6 - * - * start size - * cbus mux 0x202c 40 - * cbus pu_pd 0x203a 24 - * cbus pull_en 0x203a 24 - * aobus mux 0x0005 4 - * aobus pu_pd 0x000b 4 - * aobus pull_en 0x000b 4 - * - * For simplicity we don't support setting pull for gpioe and gpioz. - */ - -static struct aml8726_pinctrl_pkg_pin aml8726_m6_pkg_pin[] = { - { "card_0", false, 12, 0x00100000 }, - { "card_1", false, 12, 0x00200000 }, - { "card_2", false, 12, 0x00400000 }, - { "card_3", false, 12, 0x00800000 }, - { "card_4", false, 12, 0x01000000 }, - { "card_5", false, 12, 0x02000000 }, - { "card_6", false, 12, 0x04000000 }, - - { "gpioc_10", false, 8, 0x00000400 }, - { "gpioc_11", false, 8, 0x00000800 }, - { "gpioc_12", false, 8, 0x00001000 }, - { "gpioc_13", false, 8, 0x00002000 }, - - { "gpiox_13", false, 16, 0x00002000 }, - { "gpiox_14", false, 16, 0x00004000 }, - { "gpiox_15", false, 16, 0x00008000 }, - { "gpiox_16", false, 16, 0x00010000 }, - { "gpiox_17", false, 16, 0x00020000 }, - { "gpiox_18", false, 16, 0x00040000 }, - { "gpiox_19", false, 16, 0x00080000 }, - { "gpiox_20", false, 16, 0x00100000 }, - { "gpiox_21", false, 16, 0x00200000 }, - { "gpiox_22", false, 16, 0x00400000 }, - { "gpiox_23", false, 16, 0x00800000 }, - { "gpiox_24", false, 16, 0x01000000 }, - { "gpiox_25", false, 16, 0x02000000 }, - { "gpiox_26", false, 16, 0x04000000 }, - { "gpiox_27", false, 16, 0x08000000 }, - { "gpiox_28", false, 16, 0x10000000 }, - - { "gpioy_0", false, 20, 0x00000010 }, - { "gpioy_1", false, 20, 0x00000020 }, - { "gpioy_2", false, 20, 0x00000040 }, - { "gpioy_3", false, 20, 0x00000080 }, - { "gpioy_4", false, 20, 0x00000100 }, - { "gpioy_5", false, 20, 0x00000200 }, - { "gpioy_6", false, 20, 0x00000400 }, - { "gpioy_7", false, 20, 0x00000800 }, - { "gpioy_8", false, 20, 0x00001000 }, - { "gpioy_9", false, 20, 0x00002000 }, - { "gpioy_10", false, 20, 0x00004000 }, - { "gpioy_11", false, 20, 0x00008000 }, - { "gpioy_12", false, 20, 0x00010000 }, - { "gpioy_13", false, 20, 0x00020000 }, - { "gpioy_14", false, 20, 0x00040000 }, - - { "gpioao_0", true, 0, 0x00000001 }, - { "gpioao_1", true, 0, 0x00000002 }, - { "gpioao_2", true, 0, 0x00000004 }, - { "gpioao_3", true, 0, 0x00000008 }, - { "gpioao_4", true, 0, 0x00000010 }, - { "gpioao_5", true, 0, 0x00000020 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_gpio[] = { - { "card_0", "card_0", 0, 0x00000000 }, - { "card_1", "card_1", 0, 0x00000000 }, - { "card_2", "card_2", 0, 0x00000000 }, - { "card_3", "card_3", 0, 0x00000000 }, - { "card_4", "card_4", 0, 0x00000000 }, - { "card_5", "card_5", 0, 0x00000000 }, - { "card_6", "card_6", 0, 0x00000000 }, - - { "gpioc_10", "gpioc_10", 0, 0x00000000 }, - { "gpioc_11", "gpioc_11", 0, 0x00000000 }, - { "gpioc_12", "gpioc_12", 0, 0x00000000 }, - { "gpioc_13", "gpioc_13", 0, 0x00000000 }, - - { "gpiox_13", "gpiox_13", 0, 0x00000000 }, - { "gpiox_14", "gpiox_14", 0, 0x00000000 }, - { "gpiox_15", "gpiox_15", 0, 0x00000000 }, - { "gpiox_16", "gpiox_16", 0, 0x00000000 }, - { "gpiox_17", "gpiox_17", 0, 0x00000000 }, - { "gpiox_18", "gpiox_18", 0, 0x00000000 }, - { "gpiox_19", "gpiox_19", 0, 0x00000000 }, - { "gpiox_20", "gpiox_20", 0, 0x00000000 }, - { "gpiox_21", "gpiox_21", 0, 0x00000000 }, - { "gpiox_22", "gpiox_22", 0, 0x00000000 }, - { "gpiox_23", "gpiox_23", 0, 0x00000000 }, - { "gpiox_24", "gpiox_24", 0, 0x00000000 }, - { "gpiox_25", "gpiox_25", 0, 0x00000000 }, - { "gpiox_26", "gpiox_26", 0, 0x00000000 }, - { "gpiox_27", "gpiox_27", 0, 0x00000000 }, - { "gpiox_28", "gpiox_28", 0, 0x00000000 }, - - { "gpioy_0", "gpioy_0", 0, 0x00000000 }, - { "gpioy_1", "gpioy_1", 0, 0x00000000 }, - { "gpioy_2", "gpioy_2", 0, 0x00000000 }, - { "gpioy_3", "gpioy_3", 0, 0x00000000 }, - { "gpioy_4", "gpioy_4", 0, 0x00000000 }, - { "gpioy_5", "gpioy_5", 0, 0x00000000 }, - { "gpioy_6", "gpioy_6", 0, 0x00000000 }, - { "gpioy_7", "gpioy_7", 0, 0x00000000 }, - { "gpioy_8", "gpioy_8", 0, 0x00000000 }, - { "gpioy_9", "gpioy_9", 0, 0x00000000 }, - { "gpioy_10", "gpioy_10", 0, 0x00000000 }, - { "gpioy_11", "gpioy_11", 0, 0x00000000 }, - { "gpioy_12", "gpioy_12", 0, 0x00000000 }, - { "gpioy_13", "gpioy_13", 0, 0x00000000 }, - { "gpioy_14", "gpioy_14", 0, 0x00000000 }, - - { "gpioao_0", "gpioao_0", 0, 0x00000000 }, - { "gpioao_1", "gpioao_1", 0, 0x00000000 }, - { "gpioao_2", "gpioao_2", 0, 0x00000000 }, - { "gpioao_3", "gpioao_3", 0, 0x00000000 }, - { "gpioao_4", "gpioao_4", 0, 0x00000000 }, - { "gpioao_5", "gpioao_5", 0, 0x00000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_ethernet[] = { - { "ref_clk_in", "gpioy_0", 24, 0x80000000 }, - { "ref_clk_out", "gpioy_0", 24, 0x40000000 }, - { "tx_clk", "gpioy_1", 24, 0x00040000 }, - { "tx_en", "gpioy_2", 24, 0x00020000 }, - { "tx_d0", "gpioy_6", 24, 0x00002000 }, - { "tx_d1", "gpioy_5", 24, 0x00004000 }, - { "tx_d2", "gpioy_4", 24, 0x00008000 }, - { "tx_d3", "gpioy_3", 24, 0x00010000 }, - { "rx_clk", "gpioy_7", 24, 0x00001000 }, - { "rx_dv", "gpioy_8", 24, 0x00000800 }, - { "rx_d0", "gpioy_12", 24, 0x00000080 }, - { "rx_d1", "gpioy_11", 24, 0x00000100 }, - { "rx_d2", "gpioy_10", 24, 0x00000200 }, - { "rx_d3", "gpioy_9", 24, 0x00000400 }, - { "mdc", "gpioy_14", 24, 0x00000020 }, - { "mdio", "gpioy_13", 24, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_hdmi[] = { - { "cec", "gpioc_13", 4, 0x02000000 }, - { "hpd", "gpioc_10", 4, 0x00400000 }, - { "scl", "gpioc_12", 4, 0x01000000 }, - { "sda", "gpioc_11", 4, 0x00800000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_i2c_a[] = { - { "scl", "gpiox_26", 20, 0x04000000 }, - { "sda", "gpiox_25", 20, 0x08000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_i2c_b[] = { - { "scl", "gpiox_28", 20, 0x40000000 }, - { "sda", "gpiox_27", 20, 0x80000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_sdio_b[] = { - { "clk", "card_4", 8, 0x00000800 }, - { "cmd", "card_5", 8, 0x00000400 }, - { "d0", "card_0", 8, 0x00008000 }, - { "d1", "card_1", 8, 0x00004000 }, - { "d2", "card_2", 8, 0x00002000 }, - { "d3", "card_3", 8, 0x00001000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_sdxc_b[] = { - { "clk", "card_4", 8, 0x00000020 }, - { "cmd", "card_5", 8, 0x00000010 }, - { "d0", "card_0", 8, 0x00000080 }, - { "d1", "card_1", 8, 0x00000040 }, - { "d2", "card_2", 8, 0x00000040 }, - { "d3", "card_3", 8, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_uart_a[] = { - { "tx", "gpiox_13", 16, 0x00002000 }, - { "rx", "gpiox_14", 16, 0x00001000 }, - { "cts", "gpiox_15", 16, 0x00000800 }, - { "rts", "gpiox_16", 16, 0x00000400 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_uart_b[] = { - { "tx", "gpiox_17", 16, 0x00000200 }, - { "rx", "gpiox_18", 16, 0x00000100 }, - { "cts", "gpiox_19", 16, 0x00000080 }, - { "rts", "gpiox_20", 16, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_uart_c[] = { - { "tx", "gpiox_21", 16, 0x00000008 }, - { "rx", "gpiox_22", 16, 0x00000004 }, - { "cts", "gpiox_23", 16, 0x00000002 }, - { "rts", "gpiox_24", 16, 0x00000001 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_i2c_ao[] = { - { "scl", "gpioao_4", 0, 0x00000400 }, - { "sda", "gpioao_5", 0, 0x00000200 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m6_uart_ao[] = { - { "tx", "gpioao_0", 0, 0x00001000 }, - { "rx", "gpioao_1", 0, 0x00000800 }, - { "cts", "gpioao_2", 0, 0x00000400 }, - { "rts", "gpioao_3", 0, 0x00000200 }, - { NULL } -}; - -struct aml8726_pinctrl_function aml8726_m6_pinctrl[] = { - { "gpio", aml8726_m6_gpio }, - { "ethernet", aml8726_m6_ethernet }, - { "hdmi", aml8726_m6_hdmi }, - { "i2c-a", aml8726_m6_i2c_a }, - { "i2c-b", aml8726_m6_i2c_b }, - { "sdio-b", aml8726_m6_sdio_b }, - { "sdxc-b", aml8726_m6_sdxc_b }, - { "uart-a", aml8726_m6_uart_a }, - { "uart-b", aml8726_m6_uart_b }, - { "uart-c", aml8726_m6_uart_c }, - { "i2c-ao", aml8726_m6_i2c_ao }, - { "uart-ao", aml8726_m6_uart_ao }, - { NULL } -}; - -/* - * aml8726-m8 - * - * start size - * cbus mux 0x202c 40 - * cbus pu_pd 0x203a 20 - * cbus pull_en 0x2048 20 - * aobus mux 0x0005 4 - * aobus pu_pd 0x000b 4 - * aobus pull_en 0x000b 4 - */ - -static struct aml8726_pinctrl_pkg_pin aml8726_m8_pkg_pin[] = { - { "boot_0", false, 8, 0x00000001 }, - { "boot_1", false, 8, 0x00000002 }, - { "boot_2", false, 8, 0x00000004 }, - { "boot_3", false, 8, 0x00000008 }, - { "boot_4", false, 8, 0x00000010 }, - { "boot_5", false, 8, 0x00000020 }, - { "boot_6", false, 8, 0x00000040 }, - { "boot_7", false, 8, 0x00000080 }, - - { "boot_16", false, 8, 0x00010000 }, - { "boot_17", false, 8, 0x00020000 }, - - { "card_0", false, 8, 0x00100000 }, - { "card_1", false, 8, 0x00200000 }, - { "card_2", false, 8, 0x00400000 }, - { "card_3", false, 8, 0x00800000 }, - { "card_4", false, 8, 0x01000000 }, - { "card_5", false, 8, 0x02000000 }, - { "card_6", false, 8, 0x04000000 }, - - { "gpioh_0", false, 4, 0x00001000 }, - { "gpioh_1", false, 4, 0x00002000 }, - { "gpioh_2", false, 4, 0x00004000 }, - { "gpioh_3", false, 4, 0x00008000 }, - - { "gpiox_12", false, 16, 0x00001000 }, - { "gpiox_13", false, 16, 0x00002000 }, - { "gpiox_14", false, 16, 0x00004000 }, - { "gpiox_15", false, 16, 0x00008000 }, - { "gpiox_16", false, 16, 0x00010000 }, - { "gpiox_17", false, 16, 0x00020000 }, - { "gpiox_18", false, 16, 0x00040000 }, - { "gpiox_19", false, 16, 0x00080000 }, - - { "gpioy_0", false, 12, 0x00000001 }, - { "gpioy_1", false, 12, 0x00000002 }, - { "gpioy_2", false, 12, 0x00000004 }, - { "gpioy_3", false, 12, 0x00000008 }, - - { "gpioz_2", false, 4, 0x00000004 }, - { "gpioz_3", false, 4, 0x00000008 }, - { "gpioz_4", false, 4, 0x00000010 }, - { "gpioz_5", false, 4, 0x00000020 }, - { "gpioz_6", false, 4, 0x00000040 }, - { "gpioz_7", false, 4, 0x00000080 }, - { "gpioz_8", false, 4, 0x00000100 }, - { "gpioz_9", false, 4, 0x00000200 }, - { "gpioz_10", false, 4, 0x00000400 }, - { "gpioz_11", false, 4, 0x00000800 }, - { "gpioz_12", false, 4, 0x00001000 }, - { "gpioz_13", false, 4, 0x00002000 }, - - { "gpioao_0", true, 0, 0x00000001 }, - { "gpioao_1", true, 0, 0x00000002 }, - { "gpioao_2", true, 0, 0x00000004 }, - { "gpioao_3", true, 0, 0x00000008 }, - { "gpioao_4", true, 0, 0x00000010 }, - { "gpioao_5", true, 0, 0x00000020 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_gpio[] = { - { "boot_0", "boot_0", 0, 0x00000000 }, - { "boot_1", "boot_1", 0, 0x00000000 }, - { "boot_2", "boot_2", 0, 0x00000000 }, - { "boot_3", "boot_3", 0, 0x00000000 }, - { "boot_4", "boot_4", 0, 0x00000000 }, - { "boot_5", "boot_5", 0, 0x00000000 }, - { "boot_6", "boot_6", 0, 0x00000000 }, - { "boot_7", "boot_7", 0, 0x00000000 }, - - { "boot_16", "boot_16", 0, 0x00000000 }, - { "boot_17", "boot_17", 0, 0x00000000 }, - - { "card_0", "card_0", 0, 0x00000000 }, - { "card_1", "card_1", 0, 0x00000000 }, - { "card_2", "card_2", 0, 0x00000000 }, - { "card_3", "card_3", 0, 0x00000000 }, - { "card_4", "card_4", 0, 0x00000000 }, - { "card_5", "card_5", 0, 0x00000000 }, - { "card_6", "card_6", 0, 0x00000000 }, - - { "gpioh_0", "gpioh_0", 0, 0x00000000 }, - { "gpioh_1", "gpioh_1", 0, 0x00000000 }, - { "gpioh_2", "gpioh_2", 0, 0x00000000 }, - { "gpioh_3", "gpioh_3", 0, 0x00000000 }, - - { "gpiox_12", "gpiox_12", 0, 0x00000000 }, - { "gpiox_13", "gpiox_13", 0, 0x00000000 }, - { "gpiox_14", "gpiox_14", 0, 0x00000000 }, - { "gpiox_15", "gpiox_15", 0, 0x00000000 }, - { "gpiox_16", "gpiox_16", 0, 0x00000000 }, - { "gpiox_17", "gpiox_17", 0, 0x00000000 }, - { "gpiox_18", "gpiox_18", 0, 0x00000000 }, - { "gpiox_19", "gpiox_19", 0, 0x00000000 }, - - { "gpioy_0", "gpioy_0", 0, 0x00000000 }, - { "gpioy_1", "gpioy_1", 0, 0x00000000 }, - { "gpioy_2", "gpioy_2", 0, 0x00000000 }, - { "gpioy_3", "gpioy_3", 0, 0x00000000 }, - - { "gpioz_2", "gpioz_2", 0, 0x00000000 }, - { "gpioz_3", "gpioz_3", 0, 0x00000000 }, - { "gpioz_4", "gpioz_4", 0, 0x00000000 }, - { "gpioz_5", "gpioz_5", 0, 0x00000000 }, - { "gpioz_6", "gpioz_6", 0, 0x00000000 }, - { "gpioz_7", "gpioz_7", 0, 0x00000000 }, - { "gpioz_8", "gpioz_8", 0, 0x00000000 }, - { "gpioz_9", "gpioz_9", 0, 0x00000000 }, - { "gpioz_10", "gpioz_10", 0, 0x00000000 }, - { "gpioz_11", "gpioz_11", 0, 0x00000000 }, - { "gpioz_12", "gpioz_12", 0, 0x00000000 }, - { "gpioz_13", "gpioz_13", 0, 0x00000000 }, - - { "gpioao_0", "gpioao_0", 0, 0x00000000 }, - { "gpioao_1", "gpioao_1", 0, 0x00000000 }, - { "gpioao_2", "gpioao_2", 0, 0x00000000 }, - { "gpioao_3", "gpioao_3", 0, 0x00000000 }, - { "gpioao_4", "gpioao_4", 0, 0x00000000 }, - { "gpioao_5", "gpioao_5", 0, 0x00000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_ethernet[] = { - { "tx_clk", "gpioz_4", 24, 0x00008000 }, - { "tx_en", "gpioz_5", 24, 0x00004000 }, - { "tx_d0", "gpioz_7", 24, 0x00001000 }, - { "tx_d1", "gpioz_6", 24, 0x00002000 }, - { "rx_clk_in", "gpioz_8", 24, 0x00000400 }, - { "rx_clk_out", "gpioz_8", 24, 0x00000200 }, - { "rx_dv", "gpioz_9", 24, 0x00000800 }, - { "rx_d0", "gpioz_11", 24, 0x00000080 }, - { "rx_d1", "gpioz_10", 24, 0x00000100 }, - { "mdc", "gpioz_13", 24, 0x00000020 }, - { "mdio", "gpioz_12", 24, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_hdmi[] = { - { "cec", "gpioh_3", 4, 0x00800000 }, - { "hpd", "gpioh_0", 4, 0x04000000 }, - { "scl", "gpioh_2", 4, 0x01000000 }, - { "sda", "gpioh_1", 4, 0x02000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_i2c_a[] = { - { "scl", "gpioz_12", 20, 0x00000040 }, - { "sda", "gpioz_11", 20, 0x00000080 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_i2c_b[] = { - { "scl", "gpioz_3", 20, 0x04000000 }, - { "sda", "gpioz_2", 20, 0x08000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_sdio_b[] = { - { "clk", "card_2", 8, 0x00000800 }, - { "cmd", "card_3", 8, 0x00000400 }, - { "d0", "card_1", 8, 0x00008000 }, - { "d1", "card_0", 8, 0x00004000 }, - { "d2", "card_5", 8, 0x00002000 }, - { "d3", "card_4", 8, 0x00001000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_sdxc_b[] = { - { "clk", "card_2", 8, 0x00000020 }, - { "cmd", "card_3", 8, 0x00000010 }, - { "d0", "card_1", 8, 0x00000080 }, - { "d1", "card_0", 8, 0x00000040 }, - { "d2", "card_5", 8, 0x00000040 }, - { "d3", "card_4", 8, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_sdio_c[] = { - { "clk", "boot_17", 24, 0x01000000 }, - { "cmd", "boot_16", 24, 0x02000000 }, - { "d0", "boot_0", 24, 0x20000000 }, - { "d1", "boot_1", 24, 0x10000000 }, - { "d2", "boot_2", 24, 0x08000000 }, - { "d3", "boot_3", 24, 0x04000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_sdxc_c[] = { - { "clk", "boot_17", 16, 0x04000000 }, - { "cmd", "boot_16", 16, 0x08000000 }, - { "d0", "boot_0", 16, 0x40000000 }, - { "d1", "boot_1", 16, 0x20000000 }, - { "d2", "boot_2", 16, 0x20000000 }, - { "d3", "boot_3", 16, 0x20000000 }, - { "d4", "boot_4", 16, 0x10000000 }, - { "d5", "boot_5", 16, 0x10000000 }, - { "d6", "boot_6", 16, 0x10000000 }, - { "d7", "boot_7", 16, 0x10000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_uart_a[] = { - { "tx", "gpiox_4", 16, 0x00020000 }, - { "rx", "gpiox_5", 16, 0x00010000 }, - { "cts", "gpiox_6", 16, 0x00008000 }, - { "rts", "gpiox_7", 16, 0x00004000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_uart_b[] = { - { "tx", "gpiox_16", 16, 0x00000200 }, - { "rx", "gpiox_17", 16, 0x00000100 }, - { "cts", "gpiox_18", 16, 0x00000080 }, - { "rts", "gpiox_19", 16, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_uart_c[] = { - { "tx", "gpioy_0", 4, 0x00080000 }, - { "rx", "gpioy_1", 4, 0x00040000 }, - { "cts", "gpioy_2", 4, 0x00020000 }, - { "rts", "gpioy_3", 4, 0x00010000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_i2c_ao[] = { - { "scl", "gpioao_4", 0, 0x00000400 }, - { "sda", "gpioao_5", 0, 0x00000200 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8_uart_ao[] = { - { "tx", "gpioao_0", 0, 0x00001000 }, - { "rx", "gpioao_1", 0, 0x00000800 }, - { "cts", "gpioao_2", 0, 0x00000400 }, - { "rts", "gpioao_3", 0, 0x00000200 }, - { NULL } -}; - -struct aml8726_pinctrl_function aml8726_m8_pinctrl[] = { - { "gpio", aml8726_m8_gpio }, - { "ethernet", aml8726_m8_ethernet }, - { "hdmi", aml8726_m8_hdmi }, - { "i2c-a", aml8726_m8_i2c_a }, - { "i2c-b", aml8726_m8_i2c_b }, - { "sdio-b", aml8726_m8_sdio_b }, - { "sdxc-b", aml8726_m8_sdxc_b }, - { "sdio-c", aml8726_m8_sdio_c }, - { "sdxc-c", aml8726_m8_sdxc_c }, - { "uart-a", aml8726_m8_uart_a }, - { "uart-b", aml8726_m8_uart_b }, - { "uart-c", aml8726_m8_uart_c }, - { "i2c-ao", aml8726_m8_i2c_ao }, - { "uart-ao", aml8726_m8_uart_ao }, - { NULL } -}; - -/* - * aml8726-m8b - * - * start size - * cbus mux 0x202c 40 - * cbus pu_pd 0x203a 24 - * cbus pull_en 0x2048 24 - * aobus mux 0x0005 4 - * aobus pu_pd 0x000b 4 - * aobus pull_en 0x000b 4 - */ - -static struct aml8726_pinctrl_pkg_pin aml8726_m8b_pkg_pin[] = { - { "boot_0", false, 8, 0x00000001 }, - { "boot_1", false, 8, 0x00000002 }, - { "boot_2", false, 8, 0x00000004 }, - { "boot_3", false, 8, 0x00000008 }, - { "boot_4", false, 8, 0x00000010 }, - { "boot_5", false, 8, 0x00000020 }, - { "boot_6", false, 8, 0x00000040 }, - { "boot_7", false, 8, 0x00000080 }, - { "boot_8", false, 8, 0x00000100 }, - { "boot_9", false, 8, 0x00000200 }, - { "boot_10", false, 8, 0x00000400 }, - - { "card_0", false, 8, 0x00100000 }, - { "card_1", false, 8, 0x00200000 }, - { "card_2", false, 8, 0x00400000 }, - { "card_3", false, 8, 0x00800000 }, - { "card_4", false, 8, 0x01000000 }, - { "card_5", false, 8, 0x02000000 }, - { "card_6", false, 8, 0x04000000 }, - - { "dif_0p", false, 20, 0x00000100 }, - { "dif_0n", false, 20, 0x00000200 }, - { "dif_1p", false, 20, 0x00000400 }, - { "dif_1n", false, 20, 0x00000800 }, - { "dif_2p", false, 20, 0x00001000 }, - { "dif_2n", false, 20, 0x00002000 }, - { "dif_3p", false, 20, 0x00004000 }, - { "dif_3n", false, 20, 0x00008000 }, - { "dif_4p", false, 20, 0x00010000 }, - { "dif_4n", false, 20, 0x00020000 }, - - { "gpiodv_24", false, 0, 0x01000000 }, - { "gpiodv_25", false, 0, 0x02000000 }, - { "gpiodv_26", false, 0, 0x04000000 }, - { "gpiodv_27", false, 0, 0x08000000 }, - - { "gpioh_0", false, 4, 0x00010000 }, - { "gpioh_1", false, 4, 0x00020000 }, - { "gpioh_2", false, 4, 0x00040000 }, - { "gpioh_3", false, 4, 0x00080000 }, - { "gpioh_4", false, 4, 0x00100000 }, - { "gpioh_5", false, 4, 0x00200000 }, - { "gpioh_6", false, 4, 0x00400000 }, - { "gpioh_7", false, 4, 0x00800000 }, - { "gpioh_8", false, 4, 0x01000000 }, - { "gpioh_9", false, 4, 0x02000000 }, - - { "gpiox_4", false, 16, 0x00000010 }, - { "gpiox_5", false, 16, 0x00000020 }, - { "gpiox_6", false, 16, 0x00000040 }, - { "gpiox_7", false, 16, 0x00000080 }, - { "gpiox_16", false, 16, 0x00010000 }, - { "gpiox_17", false, 16, 0x00020000 }, - { "gpiox_18", false, 16, 0x00040000 }, - { "gpiox_19", false, 16, 0x00080000 }, - - { "gpioao_0", true, 0, 0x00000001 }, - { "gpioao_1", true, 0, 0x00000002 }, - { "gpioao_2", true, 0, 0x00000004 }, - { "gpioao_3", true, 0, 0x00000008 }, - { "gpioao_4", true, 0, 0x00000010 }, - { "gpioao_5", true, 0, 0x00000020 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_gpio[] = { - { "boot_0", "boot_0", 0, 0x00000000 }, - { "boot_1", "boot_1", 0, 0x00000000 }, - { "boot_2", "boot_2", 0, 0x00000000 }, - { "boot_3", "boot_3", 0, 0x00000000 }, - { "boot_4", "boot_4", 0, 0x00000000 }, - { "boot_5", "boot_5", 0, 0x00000000 }, - { "boot_6", "boot_6", 0, 0x00000000 }, - { "boot_7", "boot_7", 0, 0x00000000 }, - { "boot_8", "boot_8", 0, 0x00000000 }, - { "boot_9", "boot_9", 0, 0x00000000 }, - { "boot_10", "boot_10", 0, 0x00000000 }, - - { "card_0", "card_0", 0, 0x00000000 }, - { "card_1", "card_1", 0, 0x00000000 }, - { "card_2", "card_2", 0, 0x00000000 }, - { "card_3", "card_3", 0, 0x00000000 }, - { "card_4", "card_4", 0, 0x00000000 }, - { "card_5", "card_5", 0, 0x00000000 }, - { "card_6", "card_6", 0, 0x00000000 }, - - { "dif_0p", "dif_0p", 0, 0x00000000 }, - { "dif_0n", "dif_0n", 0, 0x00000000 }, - { "dif_1p", "dif_1p", 0, 0x00000000 }, - { "dif_1n", "dif_1n", 0, 0x00000000 }, - { "dif_2p", "dif_2p", 0, 0x00000000 }, - { "dif_2n", "dif_2n", 0, 0x00000000 }, - { "dif_3p", "dif_3p", 0, 0x00000000 }, - { "dif_3n", "dif_3n", 0, 0x00000000 }, - { "dif_4p", "dif_4p", 0, 0x00000000 }, - { "dif_4n", "dif_4n", 0, 0x00000000 }, - - { "gpiodv_24", "gpiodv_24", 0, 0x00000000 }, - { "gpiodv_25", "gpiodv_25", 0, 0x00000000 }, - { "gpiodv_26", "gpiodv_26", 0, 0x00000000 }, - { "gpiodv_27", "gpiodv_27", 0, 0x00000000 }, - - { "gpioh_0", "gpioh_0", 0, 0x00000000 }, - { "gpioh_1", "gpioh_1", 0, 0x00000000 }, - { "gpioh_2", "gpioh_2", 0, 0x00000000 }, - { "gpioh_3", "gpioh_3", 0, 0x00000000 }, - { "gpioh_4", "gpioh_4", 0, 0x00000000 }, - { "gpioh_5", "gpioh_5", 0, 0x00000000 }, - { "gpioh_6", "gpioh_6", 0, 0x00000000 }, - { "gpioh_7", "gpioh_7", 0, 0x00000000 }, - { "gpioh_8", "gpioh_8", 0, 0x00000000 }, - { "gpioh_9", "gpioh_9", 0, 0x00000000 }, - - { "gpiox_4", "gpiox_4", 0, 0x00000000 }, - { "gpiox_5", "gpiox_5", 0, 0x00000000 }, - { "gpiox_6", "gpiox_6", 0, 0x00000000 }, - { "gpiox_7", "gpiox_7", 0, 0x00000000 }, - { "gpiox_16", "gpiox_16", 0, 0x00000000 }, - { "gpiox_17", "gpiox_17", 0, 0x00000000 }, - { "gpiox_18", "gpiox_18", 0, 0x00000000 }, - { "gpiox_19", "gpiox_19", 0, 0x00000000 }, - - { "gpioao_0", "gpioao_0", 0, 0x00000000 }, - { "gpioao_1", "gpioao_1", 0, 0x00000000 }, - { "gpioao_2", "gpioao_2", 0, 0x00000000 }, - { "gpioao_3", "gpioao_3", 0, 0x00000000 }, - { "gpioao_4", "gpioao_4", 0, 0x00000000 }, - { "gpioao_5", "gpioao_5", 0, 0x00000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_ethernet[] = { - { "ref_clk", "dif_3n", 24, 0x00000100 }, - { "tx_clk", "gpioh_9", 24, 0x00000800 }, - { "tx_en", "dif_3p", 24, 0x00000040 }, - { "tx_d0", "gpioh_6", 28, 0x00100000 }, - { "tx_d1", "gpioh_5", 28, 0x00200000 }, - { "tx_d2", "gpioh_8", 24, 0x00001000 }, - { "tx_d3", "gpioh_7", 24, 0x00002000 }, - { "rx_clk", "dif_1n", 24, 0x00000008 }, - { "rx_dv", "dif_1p", 24, 0x00000004 }, - { "rx_d0", "dif_0n", 24, 0x00000002 }, - { "rx_d1", "dif_0p", 24, 0x00000001 }, - { "rx_d2", "dif_2n", 28, 0x00800000 }, - { "rx_d3", "dif_2p", 28, 0x00400000 }, - { "mdc", "dif_4p", 24, 0x00000200 }, - { "mdio", "dif_4n", 24, 0x00000400 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_hdmi[] = { - { "cec", "gpioh_3", 4, 0x00800000 }, - { "hpd", "gpioh_0", 4, 0x04000000 }, - { "scl", "gpioh_2", 4, 0x01000000 }, - { "sda", "gpioh_1", 4, 0x02000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_i2c_a[] = { - { "scl", "gpiodv_25", 36, 0x40000000 }, - { "sda", "gpiodv_24", 36, 0x80000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_i2c_b[] = { - { "scl", "gpiodv_27", 36, 0x10000000 }, - { "sda", "gpiodv_26", 36, 0x20000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_sdio_b[] = { - { "clk", "card_2", 8, 0x00000800 }, - { "cmd", "card_3", 8, 0x00000400 }, - { "d0", "card_1", 8, 0x00008000 }, - { "d1", "card_0", 8, 0x00004000 }, - { "d2", "card_5", 8, 0x00002000 }, - { "d3", "card_4", 8, 0x00001000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_sdxc_b[] = { - { "clk", "card_2", 8, 0x00000020 }, - { "cmd", "card_3", 8, 0x00000010 }, - { "d0", "card_1", 8, 0x00000080 }, - { "d1", "card_0", 8, 0x00000040 }, - { "d2", "card_5", 8, 0x00000040 }, - { "d3", "card_4", 8, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_sdio_c[] = { - { "clk", "boot_8", 24, 0x80000000 }, - { "cmd", "boot_10", 24, 0x40000000 }, - { "d0", "boot_0", 24, 0x20000000 }, - { "d1", "boot_1", 24, 0x10000000 }, - { "d2", "boot_2", 24, 0x08000000 }, - { "d3", "boot_3", 24, 0x04000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_sdxc_c[] = { - { "clk", "boot_8", 28, 0x00080000 }, - { "cmd", "boot_10", 28, 0x00040000 }, - { "d0", "boot_0", 16, 0x40000000 }, - { "d1", "boot_1", 16, 0x20000000 }, - { "d2", "boot_2", 16, 0x20000000 }, - { "d3", "boot_3", 16, 0x20000000 }, - { "d4", "boot_4", 16, 0x10000000 }, - { "d5", "boot_5", 16, 0x10000000 }, - { "d6", "boot_6", 16, 0x10000000 }, - { "d7", "boot_7", 16, 0x10000000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_uart_a[] = { - { "tx", "gpiox_4", 16, 0x00020000 }, - { "rx", "gpiox_5", 16, 0x00010000 }, - { "cts", "gpiox_6", 16, 0x00008000 }, - { "rts", "gpiox_7", 16, 0x00004000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_uart_b[] = { - { "tx", "gpiox_16", 16, 0x00000200 }, - { "rx", "gpiox_17", 16, 0x00000100 }, - { "cts", "gpiox_18", 16, 0x00000080 }, - { "rts", "gpiox_19", 16, 0x00000040 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_uart_c[] = { - { "tx", "gpiodv_24", 24, 0x00800000 }, - { "rx", "gpiodv_25", 24, 0x00400000 }, - { "cts", "gpiodv_26", 24, 0x00200000 }, - { "rts", "gpiodv_27", 24, 0x00100000 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_i2c_ao[] = { - { "scl", "gpioao_4", 0, 0x00000400 }, - { "sda", "gpioao_5", 0, 0x00000200 }, - { NULL } -}; - -static struct aml8726_pinctrl_pin aml8726_m8b_uart_ao[] = { - { "tx", "gpioao_0", 0, 0x00001000 }, - { "rx", "gpioao_1", 0, 0x00000800 }, - { "cts", "gpioao_2", 0, 0x00000400 }, - { "rts", "gpioao_3", 0, 0x00000200 }, - { NULL } -}; - -struct aml8726_pinctrl_function aml8726_m8b_pinctrl[] = { - { "gpio", aml8726_m8b_gpio }, - { "ethernet", aml8726_m8b_ethernet }, - { "hdmi", aml8726_m8b_hdmi }, - { "i2c-a", aml8726_m8b_i2c_a }, - { "i2c-b", aml8726_m8b_i2c_b }, - { "sdio-b", aml8726_m8b_sdio_b }, - { "sdxc-b", aml8726_m8b_sdxc_b }, - { "sdio-c", aml8726_m8b_sdio_c }, - { "sdxc-c", aml8726_m8b_sdxc_c }, - { "uart-a", aml8726_m8b_uart_a }, - { "uart-b", aml8726_m8b_uart_b }, - { "uart-c", aml8726_m8b_uart_c }, - { "i2c-ao", aml8726_m8b_i2c_ao }, - { "uart-ao", aml8726_m8b_uart_ao }, - { NULL } -}; - -#endif /* _ARM_AMLOGIC_AML8726_PINCTRL_H */ Index: head/sys/arm/amlogic/aml8726/aml8726_pinctrl.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_pinctrl.c +++ head/sys/arm/amlogic/aml8726/aml8726_pinctrl.c @@ -1,430 +0,0 @@ -/*- - * Copyright 2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 pinctrl driver. - * - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -struct aml8726_pinctrl_softc { - device_t dev; - struct { - struct aml8726_pinctrl_function *func; - struct aml8726_pinctrl_pkg_pin *ppin; - boolean_t pud_ctrl; - } soc; - struct resource *res[6]; - struct mtx mtx; -}; - -static struct resource_spec aml8726_pinctrl_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* mux */ - { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_SHAREABLE }, /* pu/pd */ - { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_SHAREABLE }, /* pull enable */ - { SYS_RES_MEMORY, 3, RF_ACTIVE }, /* ao mux */ - { SYS_RES_MEMORY, 4, RF_ACTIVE | RF_SHAREABLE }, /* ao pu/pd */ - { SYS_RES_MEMORY, 5, RF_ACTIVE | RF_SHAREABLE }, /* ao pull enable */ - { -1, 0 } -}; - -#define AML_PINCTRL_LOCK(sc) mtx_lock(&(sc)->mtx) -#define AML_PINCTRL_UNLOCK(sc) mtx_unlock(&(sc)->mtx) -#define AML_PINCTRL_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "pinctrl", MTX_DEF) -#define AML_PINCTRL_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define MUX_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define MUX_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) - -#define PUD_WRITE_4(sc, reg, val) bus_write_4((sc)->res[1], reg, (val)) -#define PUD_READ_4(sc, reg) bus_read_4((sc)->res[1], reg) - -#define PEN_WRITE_4(sc, reg, val) bus_write_4((sc)->res[2], reg, (val)) -#define PEN_READ_4(sc, reg) bus_read_4((sc)->res[2], reg) - -#define AOMUX_WRITE_4(sc, reg, val) bus_write_4((sc)->res[3], reg, (val)) -#define AOMUX_READ_4(sc, reg) bus_read_4((sc)->res[3], reg) - -#define AOPUD_WRITE_4(sc, reg, val) bus_write_4((sc)->res[4], reg, (val)) -#define AOPUD_READ_4(sc, reg) bus_read_4((sc)->res[4], reg) - -#define AOPEN_WRITE_4(sc, reg, val) bus_write_4((sc)->res[5], reg, (val)) -#define AOPEN_READ_4(sc, reg) bus_read_4((sc)->res[5], reg) - -static int -aml8726_pinctrl_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-pinctrl")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 pinctrl"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_pinctrl_attach(device_t dev) -{ - struct aml8726_pinctrl_softc *sc = device_get_softc(dev); - - sc->dev = dev; - - sc->soc.pud_ctrl = false; - - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M3: - sc->soc.func = aml8726_m3_pinctrl; - sc->soc.ppin = aml8726_m3_pkg_pin; - break; - case AML_SOC_HW_REV_M6: - sc->soc.func = aml8726_m6_pinctrl; - sc->soc.ppin = aml8726_m6_pkg_pin; - break; - case AML_SOC_HW_REV_M8: - sc->soc.func = aml8726_m8_pinctrl; - sc->soc.ppin = aml8726_m8_pkg_pin; - sc->soc.pud_ctrl = true; - break; - case AML_SOC_HW_REV_M8B: - sc->soc.func = aml8726_m8b_pinctrl; - sc->soc.ppin = aml8726_m8b_pkg_pin; - sc->soc.pud_ctrl = true; - break; - default: - device_printf(dev, "unsupported SoC\n"); - return (ENXIO); - /* NOTREACHED */ - } - - if (bus_alloc_resources(dev, aml8726_pinctrl_spec, sc->res)) { - device_printf(dev, "could not allocate resources for device\n"); - return (ENXIO); - } - - AML_PINCTRL_LOCK_INIT(sc); - - fdt_pinctrl_register(dev, "amlogic,pins"); - fdt_pinctrl_configure_tree(dev); - - return (0); -} - -static int -aml8726_pinctrl_detach(device_t dev) -{ - struct aml8726_pinctrl_softc *sc = device_get_softc(dev); - - AML_PINCTRL_LOCK_DESTROY(sc); - - bus_release_resources(dev, aml8726_pinctrl_spec, sc->res); - - return (0); -} - -static int -aml8726_pinctrl_configure_pins(device_t dev, phandle_t cfgxref) -{ - struct aml8726_pinctrl_softc *sc = device_get_softc(dev); - struct aml8726_pinctrl_function *cf; - struct aml8726_pinctrl_function *f; - struct aml8726_pinctrl_pkg_pin *pp; - struct aml8726_pinctrl_pin *cp; - struct aml8726_pinctrl_pin *p; - enum aml8726_pinctrl_pull_mode pm; - char *function_name; - char *pins; - char *pin_name; - char *pull; - phandle_t node; - ssize_t len; - uint32_t value; - - node = OF_node_from_xref(cfgxref); - - len = OF_getprop_alloc(node, "amlogic,function", - (void **)&function_name); - - if (len < 0) { - device_printf(dev, - "missing amlogic,function attribute in FDT\n"); - return (ENXIO); - } - - for (f = sc->soc.func; f->name != NULL; f++) - if (strncmp(f->name, function_name, len) == 0) - break; - - if (f->name == NULL) { - device_printf(dev, "unknown function attribute %.*s in FDT\n", - len, function_name); - OF_prop_free(function_name); - return (ENXIO); - } - - OF_prop_free(function_name); - - len = OF_getprop_alloc(node, "amlogic,pull", - (void **)&pull); - - pm = aml8726_unknown_pm; - - if (len > 0) { - if (strncmp(pull, "enable", len) == 0) - pm = aml8726_enable_pm; - else if (strncmp(pull, "disable", len) == 0) - pm = aml8726_disable_pm; - else if (strncmp(pull, "down", len) == 0) - pm = aml8726_enable_down_pm; - else if (strncmp(pull, "up", len) == 0) - pm = aml8726_enable_up_pm; - else { - device_printf(dev, - "unknown pull attribute %.*s in FDT\n", - len, pull); - OF_prop_free(pull); - return (ENXIO); - } - } - - OF_prop_free(pull); - - /* - * Setting the pull direction isn't supported on all SoC. - */ - switch (pm) { - case aml8726_enable_down_pm: - case aml8726_enable_up_pm: - if (sc->soc.pud_ctrl == false) { - device_printf(dev, - "SoC doesn't support setting pull direction.\n"); - return (ENXIO); - } - break; - default: - break; - } - - len = OF_getprop_alloc(node, "amlogic,pins", - (void **)&pins); - - if (len < 0) { - device_printf(dev, "missing amlogic,pins attribute in FDT\n"); - return (ENXIO); - } - - pin_name = pins; - - while (len) { - for (p = f->pins; p->name != NULL; p++) - if (strncmp(p->name, pin_name, len) == 0) - break; - - if (p->name == NULL) { - /* display message prior to queuing up next string */ - device_printf(dev, "unknown pin attribute %.*s in FDT\n", - len, pin_name); - } - - /* queue up next string */ - while (*pin_name && len) { - pin_name++; - len--; - } - if (len) { - pin_name++; - len--; - } - - if (p->name == NULL) - continue; - - for (pp = sc->soc.ppin; pp->pkg_name != NULL; pp++) - if (strcmp(pp->pkg_name, p->pkg_name) == 0) - break; - - if (pp->pkg_name == NULL) { - device_printf(dev, - "missing entry for package pin %s\n", - p->pkg_name); - continue; - } - - if (pm != aml8726_unknown_pm && pp->pull_bits == 0x00000000) { - device_printf(dev, - "missing pull info for package pin %s\n", - p->pkg_name); - continue; - } - - AML_PINCTRL_LOCK(sc); - - /* - * First clear all other mux bits associated with this - * package pin. This may briefly configure the pin as - * GPIO ... however this should be fine since after - * reset the default GPIO mode is input. - */ - - for (cf = sc->soc.func; cf->name != NULL; cf++) - for (cp = cf->pins; cp->name != NULL; cp++) { - if (cp == p) - continue; - if (strcmp(cp->pkg_name, p->pkg_name) != 0) - continue; - if (cp->mux_bits == 0) - continue; - if (pp->aobus == false) { - value = MUX_READ_4(sc, cp->mux_addr); - value &= ~cp->mux_bits; - MUX_WRITE_4(sc, cp->mux_addr, value); - } else { - value = AOMUX_READ_4(sc, cp->mux_addr); - value &= ~cp->mux_bits; - AOMUX_WRITE_4(sc, cp->mux_addr, value); - } - } - - /* - * Now set the desired mux bits. - * - * In the case of GPIO there's no bits to set. - */ - - if (p->mux_bits != 0) { - if (pp->aobus == false) { - value = MUX_READ_4(sc, p->mux_addr); - value |= p->mux_bits; - MUX_WRITE_4(sc, p->mux_addr, value); - } else { - value = AOMUX_READ_4(sc, p->mux_addr); - value |= p->mux_bits; - AOMUX_WRITE_4(sc, p->mux_addr, value); - } - } - - /* - * Finally set the pull mode if it was specified. - */ - - switch (pm) { - case aml8726_enable_down_pm: - case aml8726_enable_up_pm: - if (pp->aobus == false) { - value = PUD_READ_4(sc, pp->pull_addr); - if (pm == aml8726_enable_down_pm) - value &= ~pp->pull_bits; - else - value |= pp->pull_bits; - PUD_WRITE_4(sc, pp->pull_addr, value); - } else { - value = AOPUD_READ_4(sc, pp->pull_addr); - if (pm == aml8726_enable_down_pm) - value &= ~(pp->pull_bits << 16); - else - value |= (pp->pull_bits << 16); - AOPUD_WRITE_4(sc, pp->pull_addr, value); - } - /* FALLTHROUGH */ - case aml8726_disable_pm: - case aml8726_enable_pm: - if (pp->aobus == false) { - value = PEN_READ_4(sc, pp->pull_addr); - if (pm == aml8726_disable_pm) - value &= ~pp->pull_bits; - else - value |= pp->pull_bits; - PEN_WRITE_4(sc, pp->pull_addr, value); - } else { - value = AOPEN_READ_4(sc, pp->pull_addr); - if (pm == aml8726_disable_pm) - value &= ~pp->pull_bits; - else - value |= pp->pull_bits; - AOPEN_WRITE_4(sc, pp->pull_addr, value); - } - break; - default: - break; - } - - AML_PINCTRL_UNLOCK(sc); - } - - OF_prop_free(pins); - - return (0); -} - -static device_method_t aml8726_pinctrl_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_pinctrl_probe), - DEVMETHOD(device_attach, aml8726_pinctrl_attach), - DEVMETHOD(device_detach, aml8726_pinctrl_detach), - - /* fdt_pinctrl interface */ - DEVMETHOD(fdt_pinctrl_configure,aml8726_pinctrl_configure_pins), - - DEVMETHOD_END -}; - -static driver_t aml8726_pinctrl_driver = { - "pinctrl", - aml8726_pinctrl_methods, - sizeof(struct aml8726_pinctrl_softc), -}; - -static devclass_t aml8726_pinctrl_devclass; - -EARLY_DRIVER_MODULE(pinctrl, simplebus, aml8726_pinctrl_driver, - aml8726_pinctrl_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_LATE); Index: head/sys/arm/amlogic/aml8726/aml8726_rng.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_rng.c +++ head/sys/arm/amlogic/aml8726/aml8726_rng.c @@ -1,152 +0,0 @@ -/*- - * Copyright 2014 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 random number generator driver. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -struct aml8726_rng_softc { - device_t dev; - struct resource *res[1]; - struct callout co; - int ticks; -}; - -static struct resource_spec aml8726_rng_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, 0 } -}; - -#define AML_RNG_0_REG 0 -#define AML_RNG_1_REG 4 - -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) - -static void -aml8726_rng_harvest(void *arg) -{ - struct aml8726_rng_softc *sc = arg; - uint32_t rn[2]; - - rn[0] = CSR_READ_4(sc, AML_RNG_0_REG); - rn[1] = CSR_READ_4(sc, AML_RNG_1_REG); - - random_harvest(rn, sizeof(rn), RANDOM_PURE_AML8726); - - callout_reset(&sc->co, sc->ticks, aml8726_rng_harvest, sc); -} - -static int -aml8726_rng_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-rng")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 RNG"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_rng_attach(device_t dev) -{ - struct aml8726_rng_softc *sc = device_get_softc(dev); - - sc->dev = dev; - - if (bus_alloc_resources(dev, aml8726_rng_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - /* Install a periodic collector for the RNG */ - if (hz > 100) - sc->ticks = hz / 100; - else - sc->ticks = 1; - - callout_init(&sc->co, 1); - callout_reset(&sc->co, sc->ticks, aml8726_rng_harvest, sc); - - return (0); -} - -static int -aml8726_rng_detach(device_t dev) -{ - struct aml8726_rng_softc *sc = device_get_softc(dev); - - callout_drain(&sc->co); - - bus_release_resources(dev, aml8726_rng_spec, sc->res); - - return (0); -} - -static device_method_t aml8726_rng_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_rng_probe), - DEVMETHOD(device_attach, aml8726_rng_attach), - DEVMETHOD(device_detach, aml8726_rng_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_rng_driver = { - "rng", - aml8726_rng_methods, - sizeof(struct aml8726_rng_softc), -}; - -static devclass_t aml8726_rng_devclass; - -DRIVER_MODULE(aml8726_rng, simplebus, aml8726_rng_driver, - aml8726_rng_devclass, 0, 0); -MODULE_DEPEND(aml8726_rng, random, 1, 1, 1); Index: head/sys/arm/amlogic/aml8726/aml8726_rtc.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_rtc.c +++ head/sys/arm/amlogic/aml8726/aml8726_rtc.c @@ -1,488 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 RTC driver. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include - -#include "clock_if.h" - -/* - * The RTC initialization various slightly between the different chips. - * - * aml8726-m1 aml8726-m3 aml8726-m6 (and later) - * init-always true true false - * xo-init 0x0004 0x3c0a 0x180a - * gpo-init 0x100000 0x100000 0x500000 - */ - -struct aml8726_rtc_init { - boolean_t always; - uint16_t xo; - uint32_t gpo; -}; - -struct aml8726_rtc_softc { - device_t dev; - struct aml8726_rtc_init init; - struct resource * res[2]; - struct mtx mtx; -}; - -static struct resource_spec aml8726_rtc_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { SYS_RES_IRQ, 0, RF_ACTIVE }, - { -1, 0 } -}; - -#define AML_RTC_LOCK(sc) mtx_lock_spin(&(sc)->mtx) -#define AML_RTC_UNLOCK(sc) mtx_unlock_spin(&(sc)->mtx) -#define AML_RTC_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "rtc", MTX_SPIN) -#define AML_RTC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define AML_RTC_0_REG 0 -#define AML_RTC_SCLK (1 << 0) -#define AML_RTC_SDI (1 << 2) -#define AML_RTC_SEN (1 << 1) -#define AML_RTC_AS (1 << 17) -#define AML_RTC_ABSY (1 << 22) -#define AML_RTC_IRQ_DIS (1 << 12) -#define AML_RTC_1_REG 4 -#define AML_RTC_SDO (1 << 0) -#define AML_RTC_SRDY (1 << 1) -#define AML_RTC_2_REG 8 -#define AML_RTC_3_REG 12 -#define AML_RTC_MSR_BUSY (1 << 20) -#define AML_RTC_MSR_CA (1 << 17) -#define AML_RTC_MSR_DURATION_EN (1 << 16) -#define AML_RTC_MSR_DURATION_MASK 0xffff -#define AML_RTC_MSR_DURATION_SHIFT 0 -#define AML_RTC_4_REG 16 - -#define AML_RTC_TIME_SREG 0 -#define AML_RTC_GPO_SREG 1 -#define AML_RTC_GPO_LEVEL (1 << 24) -#define AML_RTC_GPO_BUSY (1 << 23) -#define AML_RTC_GPO_ACTIVE_HIGH (1 << 22) -#define AML_RTC_GPO_CMD_MASK (3 << 20) -#define AML_RTC_GPO_CMD_SHIFT 20 -#define AML_RTC_GPO_CMD_NOW (1 << 20) -#define AML_RTC_GPO_CMD_COUNT (2 << 20) -#define AML_RTC_GPO_CMD_PULSE (3 << 20) -#define AML_RTC_GPO_CNT_MASK 0xfffff -#define AML_RTC_GPO_CNT_SHIFT 0 - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) -#define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ - (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -static int -aml8726_rtc_start_transfer(struct aml8726_rtc_softc *sc) -{ - unsigned i; - - /* idle the serial interface */ - CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) & - ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI))); - - CSR_BARRIER(sc, AML_RTC_0_REG); - - /* see if it is ready for a new cycle */ - for (i = 40; i; i--) { - DELAY(5); - if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) ) - break; - } - - if (i == 0) - return (EIO); - - /* start the cycle */ - CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) | - AML_RTC_SEN)); - - return (0); -} - -static inline void -aml8726_rtc_sclk_pulse(struct aml8726_rtc_softc *sc) -{ - - DELAY(5); - - CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) | - AML_RTC_SCLK)); - - CSR_BARRIER(sc, AML_RTC_0_REG); - - DELAY(5); - - CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) & - ~AML_RTC_SCLK)); - - CSR_BARRIER(sc, AML_RTC_0_REG); -} - -static inline void -aml8726_rtc_send_bit(struct aml8726_rtc_softc *sc, unsigned bit) -{ - - if (bit) { - CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) | - AML_RTC_SDI)); - } else { - CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) & - ~AML_RTC_SDI)); - } - - aml8726_rtc_sclk_pulse(sc); -} - -static inline void -aml8726_rtc_send_addr(struct aml8726_rtc_softc *sc, u_char addr) -{ - unsigned mask; - - for (mask = 1 << 3; mask; mask >>= 1) { - if (mask == 1) { - /* final bit indicates read / write mode */ - CSR_WRITE_4(sc, AML_RTC_0_REG, - (CSR_READ_4(sc, AML_RTC_0_REG) & ~AML_RTC_SEN)); - } - aml8726_rtc_send_bit(sc, (addr & mask)); - } -} - -static inline void -aml8726_rtc_send_data(struct aml8726_rtc_softc *sc, uint32_t data) -{ - unsigned mask; - - for (mask = 1U << 31; mask; mask >>= 1) - aml8726_rtc_send_bit(sc, (data & mask)); -} - -static inline void -aml8726_rtc_recv_data(struct aml8726_rtc_softc *sc, uint32_t *dp) -{ - uint32_t data; - unsigned i; - - data = 0; - - for (i = 0; i < 32; i++) { - aml8726_rtc_sclk_pulse(sc); - data <<= 1; - data |= (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SDO) ? 1 : 0; - } - - *dp = data; -} - -static int -aml8726_rtc_sreg_read(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t *val) -{ - u_char addr; - int error; - - /* read is indicated by lsb = 0 */ - addr = (sreg << 1) | 0; - - error = aml8726_rtc_start_transfer(sc); - - if (error) - return (error); - - aml8726_rtc_send_addr(sc, addr); - aml8726_rtc_recv_data(sc, val); - - return (0); -} - -static int -aml8726_rtc_sreg_write(struct aml8726_rtc_softc *sc, u_char sreg, uint32_t val) -{ - u_char addr; - int error; - - /* write is indicated by lsb = 1 */ - addr = (sreg << 1) | 1; - - error = aml8726_rtc_start_transfer(sc); - - if (error) - return (error); - - aml8726_rtc_send_data(sc, val); - aml8726_rtc_send_addr(sc, addr); - - return (0); -} - -static int -aml8726_rtc_initialize(struct aml8726_rtc_softc *sc) -{ - int error; - unsigned i; - - /* idle the serial interface */ - CSR_WRITE_4(sc, AML_RTC_0_REG, (CSR_READ_4(sc, AML_RTC_0_REG) & - ~(AML_RTC_SCLK | AML_RTC_SEN | AML_RTC_SDI))); - - CSR_BARRIER(sc, AML_RTC_0_REG); - - /* see if it is ready for a new cycle */ - for (i = 40; i; i--) { - DELAY(5); - if ( (CSR_READ_4(sc, AML_RTC_1_REG) & AML_RTC_SRDY) ) - break; - } - - if (sc->init.always == TRUE || (CSR_READ_4(sc, AML_RTC_1_REG) & - AML_RTC_SRDY) == 0) { - /* - * The RTC has a 16 bit initialization register. The upper - * bits can be written directly. The lower bits are written - * through a shift register. - */ - - CSR_WRITE_4(sc, AML_RTC_4_REG, ((sc->init.xo >> 8) & 0xff)); - - CSR_WRITE_4(sc, AML_RTC_0_REG, - ((CSR_READ_4(sc, AML_RTC_0_REG) & 0xffffff) | - ((uint32_t)(sc->init.xo & 0xff) << 24) | AML_RTC_AS | - AML_RTC_IRQ_DIS)); - - while ((CSR_READ_4(sc, AML_RTC_0_REG) & AML_RTC_ABSY) != 0) - cpu_spinwait(); - - DELAY(2); - - error = aml8726_rtc_sreg_write(sc, AML_RTC_GPO_SREG, - sc->init.gpo); - - if (error) - return (error); - } - - return (0); -} - -static int -aml8726_rtc_check_xo(struct aml8726_rtc_softc *sc) -{ - uint32_t now, previous; - int i; - - /* - * The RTC is driven by a 32.768khz clock meaning it's period - * is roughly 30.5 us. Check that it's working (implying the - * RTC could contain a valid value) by enabling count always - * and seeing if the value changes after 200 us (per RTC User - * Guide ... presumably the extra time is to cover XO startup). - */ - - CSR_WRITE_4(sc, AML_RTC_3_REG, (CSR_READ_4(sc, AML_RTC_3_REG) | - AML_RTC_MSR_CA)); - - previous = CSR_READ_4(sc, AML_RTC_2_REG); - - for (i = 0; i < 4; i++) { - DELAY(50); - now = CSR_READ_4(sc, AML_RTC_2_REG); - if (now != previous) - break; - } - - CSR_WRITE_4(sc, AML_RTC_3_REG, (CSR_READ_4(sc, AML_RTC_3_REG) & - ~AML_RTC_MSR_CA)); - - if (now == previous) - return (EINVAL); - - return (0); -} - -static int -aml8726_rtc_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-rtc")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 RTC"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_rtc_attach(device_t dev) -{ - struct aml8726_rtc_softc *sc = device_get_softc(dev); - - sc->dev = dev; - - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M3: - sc->init.always = true; - sc->init.xo = 0x3c0a; - sc->init.gpo = 0x100000; - break; - case AML_SOC_HW_REV_M6: - case AML_SOC_HW_REV_M8: - case AML_SOC_HW_REV_M8B: - sc->init.always = false; - sc->init.xo = 0x180a; - sc->init.gpo = 0x500000; - break; - default: - device_printf(dev, "unsupported SoC\n"); - return (ENXIO); - /* NOTREACHED */ - } - - if (bus_alloc_resources(dev, aml8726_rtc_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - aml8726_rtc_initialize(sc); - - if (aml8726_rtc_check_xo(sc) != 0) { - device_printf(dev, "crystal oscillator check failed\n"); - - bus_release_resources(dev, aml8726_rtc_spec, sc->res); - - return (ENXIO); - } - - AML_RTC_LOCK_INIT(sc); - - clock_register(dev, 1000000); - - return (0); -} - -static int -aml8726_rtc_detach(device_t dev) -{ - - return (EBUSY); -} - -static int -aml8726_rtc_gettime(device_t dev, struct timespec *ts) -{ - struct aml8726_rtc_softc *sc = device_get_softc(dev); - uint32_t sec; - int error; - - AML_RTC_LOCK(sc); - - error = aml8726_rtc_sreg_read(sc, AML_RTC_TIME_SREG, &sec); - - AML_RTC_UNLOCK(sc); - - ts->tv_sec = sec; - ts->tv_nsec = 0; - - return (error); -} - -static int -aml8726_rtc_settime(device_t dev, struct timespec *ts) -{ - struct aml8726_rtc_softc *sc = device_get_softc(dev); - uint32_t sec; - int error; - - sec = ts->tv_sec; - - /* Accuracy is only one second. */ - if (ts->tv_nsec >= 500000000) - sec++; - - AML_RTC_LOCK(sc); - - error = aml8726_rtc_sreg_write(sc, AML_RTC_TIME_SREG, sec); - - AML_RTC_UNLOCK(sc); - - return (error); -} - -static device_method_t aml8726_rtc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_rtc_probe), - DEVMETHOD(device_attach, aml8726_rtc_attach), - DEVMETHOD(device_detach, aml8726_rtc_detach), - - /* Clock interface */ - DEVMETHOD(clock_gettime, aml8726_rtc_gettime), - DEVMETHOD(clock_settime, aml8726_rtc_settime), - - DEVMETHOD_END -}; - -static driver_t aml8726_rtc_driver = { - "rtc", - aml8726_rtc_methods, - sizeof(struct aml8726_rtc_softc), -}; - -static devclass_t aml8726_rtc_devclass; - -DRIVER_MODULE(rtc, simplebus, aml8726_rtc_driver, aml8726_rtc_devclass, 0, 0); Index: head/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h +++ head/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h @@ -1,223 +0,0 @@ -/*- - * Copyright 2015 John Wehle - * 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 _ARM_AMLOGIC_AML8726_SDXC_M8_H -#define _ARM_AMLOGIC_AML8726_SDXC_M8_H - -#define AML_SDXC_ALIGN_DMA 4 -#define AML_SDXC_MAX_DMA 4096 - -/* - * Timeouts are in milliseconds - * - * Read and write are per section 4.6.2 of the: - * - * SD Specifications Part 1 - * Physical Layer Simplified Specification - * Version 4.10 - */ -#define AML_SDXC_CMD_TIMEOUT 50 -#define AML_SDXC_READ_TIMEOUT 100 -#define AML_SDXC_WRITE_TIMEOUT 500 -#define AML_SDXC_MAX_TIMEOUT 5000 - -#define AML_SDXC_BUSY_POLL_INTVL 1 -#define AML_SDXC_BUSY_TIMEOUT 1000 - -/* - * There's some disagreements between the S805 documentation - * and the Amlogic Linux platform code regarding the exact - * layout of various registers ... when in doubt we follow - * the platform code. - */ - -#define AML_SDXC_CMD_ARGUMENT_REG 0 - -#define AML_SDXC_SEND_REG 4 -#define AML_SDXC_SEND_REP_PKG_CNT_MASK (0xffffU << 16) -#define AML_SDXC_SEND_REP_PKG_CNT_SHIFT 16 -#define AML_SDXC_SEND_DATA_STOP (1 << 11) -#define AML_SDXC_SEND_DATA_WRITE (1 << 10) -#define AML_SDXC_SEND_RESP_NO_CRC7_CHECK (1 << 9) -#define AML_SDXC_SEND_RESP_136 (1 << 8) -#define AML_SDXC_SEND_CMD_HAS_DATA (1 << 7) -#define AML_SDXC_SEND_CMD_HAS_RESP (1 << 6) -#define AML_SDXC_SEND_INDEX_MASK 0x3f -#define AML_SDXC_SEND_INDEX_SHIFT 0 - -#define AML_SDXC_CNTRL_REG 8 -#define AML_SDXC_CNTRL_TX_ENDIAN_MASK (7 << 29) -#define AML_SDXC_CNTRL_TX_ENDIAN_SHIFT 29 -#define AML_SDXC_CNTRL_RX_ENDIAN_MASK (7 << 24) -#define AML_SDXC_CNTRL_RX_ENDIAN_SHIFT 24 -#define AML_SDXC_CNTRL_RX_PERIOD_SHIFT 20 -#define AML_SDXC_CNTRL_RX_TIMEOUT_SHIFT 13 -#define AML_SDXC_CNTRL_PKG_LEN_MASK (0x1ff << 4) -#define AML_SDXC_CNTRL_PKG_LEN_SHIFT 4 -#define AML_SDXC_CNTRL_BUS_WIDTH_MASK (3 << 0) -#define AML_SDXC_CNTRL_BUS_WIDTH_1 (0 << 0) -#define AML_SDXC_CNTRL_BUS_WIDTH_4 (1 << 0) -#define AML_SDXC_CNTRL_BUS_WIDTH_8 (2 << 0) - -#define AML_SDXC_STATUS_REG 12 -#define AML_SDXC_STATUS_TX_CNT_MASK (0x7f << 13) -#define AML_SDXC_STATUS_TX_CNT_SHIFT 13 -#define AML_SDXC_STATUS_RX_CNT_MASK (0x7f << 6) -#define AML_SDXC_STATUS_RX_CNT_SHIFT 6 -#define AML_SDXC_STATUS_CMD (1 << 5) -#define AML_SDXC_STATUS_DAT3 (1 << 4) -#define AML_SDXC_STATUS_DAT2 (1 << 3) -#define AML_SDXC_STATUS_DAT1 (1 << 2) -#define AML_SDXC_STATUS_DAT0 (1 << 1) -#define AML_SDXC_STATUS_BUSY (1 << 0) - -#define AML_SDXC_CLK_CNTRL_REG 16 -#define AML_SDXC_CLK_CNTRL_MEM_PWR_MASK (3 << 25) -#define AML_SDXC_CLK_CNTRL_MEM_PWR_OFF (3 << 25) -#define AML_SDXC_CLK_CNTRL_MEM_PWR_ON (0 << 25) -#define AML_SDXC_CLK_CNTRL_CLK_SEL_MASK (3 << 16) -#define AML_SDXC_CLK_CNTRL_CLK_SEL_SHIFT 16 -#define AML_SDXC_CLK_CNTRL_CLK_MODULE_EN (1 << 15) -#define AML_SDXC_CLK_CNTRL_SD_CLK_EN (1 << 14) -#define AML_SDXC_CLK_CNTRL_RX_CLK_EN (1 << 13) -#define AML_SDXC_CLK_CNTRL_TX_CLK_EN (1 << 12) -#define AML_SDXC_CLK_CNTRL_CLK_DIV_MASK 0x0fff -#define AML_SDXC_CLK_CNTRL_CLK_DIV_SHIFT 0 - -#define AML_SDXC_DMA_ADDR_REG 20 - -#define AML_SDXC_PDMA_REG 24 -#define AML_SDXC_PDMA_TX_FILL (1U << 31) -#define AML_SDXC_PDMA_RX_FLUSH_NOW (1 << 30) -#define AML_SDXC_PDMA_RX_FLUSH_MODE_SW (1 << 29) -#define AML_SDXC_PDMA_TX_THOLD_MASK (0x3f << 22) -#define AML_SDXC_PDMA_TX_THOLD_SHIFT 22 -#define AML_SDXC_PDMA_RX_THOLD_MASK (0x3f << 15) -#define AML_SDXC_PDMA_RX_THOLD_SHIFT 15 -#define AML_SDXC_PDMA_RD_BURST_MASK (0x1f << 10) -#define AML_SDXC_PDMA_RD_BURST_SHIFT 10 -#define AML_SDXC_PDMA_WR_BURST_MASK (0x1f << 5) -#define AML_SDXC_PDMA_WR_BURST_SHIFT 5 -#define AML_SDXC_PDMA_DMA_URGENT (1 << 4) -#define AML_SDXC_PDMA_RESP_INDEX_MASK (7 << 1) -#define AML_SDXC_PDMA_RESP_INDEX_SHIFT 1 -#define AML_SDXC_PDMA_DMA_EN (1 << 0) - -#define AML_SDXC_MISC_REG 28 -#define AML_SDXC_MISC_TXSTART_THOLD_MASK (7U << 29) -#define AML_SDXC_MISC_TXSTART_THOLD_SHIFT 29 -#define AML_SDXC_MISC_MANUAL_STOP_MODE (1 << 28) -#define AML_SDXC_MISC_WCRC_OK_PAT_MASK (7 << 7) -#define AML_SDXC_MISC_WCRC_OK_PAT_SHIFT 7 -#define AML_SDXC_MISC_WCRC_ERR_PAT_MASK (7 << 4) -#define AML_SDXC_MISC_WCRC_ERR_PAT_SHIFT 4 - -#define AML_SDXC_DATA_REG 32 - -#define AML_SDXC_IRQ_ENABLE_REG 36 -#define AML_SDXC_IRQ_ENABLE_TX_FIFO_EMPTY (1 << 13) -#define AML_SDXC_IRQ_ENABLE_RX_FIFO_FULL (1 << 12) -#define AML_SDXC_IRQ_ENABLE_DMA_DONE (1 << 11) -#define AML_SDXC_IRQ_ENABLE_TRANSFER_DONE_OK (1 << 7) -#define AML_SDXC_IRQ_ENABLE_A_PKG_CRC_ERR (1 << 6) -#define AML_SDXC_IRQ_ENABLE_A_PKG_TIMEOUT_ERR (1 << 5) -#define AML_SDXC_IRQ_ENABLE_A_PKG_DONE_OK (1 << 4) -#define AML_SDXC_IRQ_ENABLE_RESP_CRC_ERR (1 << 2) -#define AML_SDXC_IRQ_ENABLE_RESP_TIMEOUT_ERR (1 << 1) -#define AML_SDXC_IRQ_ENABLE_RESP_OK (1 << 0) - -#define AML_SDXC_IRQ_ENABLE_STANDARD \ - (AML_SDXC_IRQ_ENABLE_TX_FIFO_EMPTY | \ - AML_SDXC_IRQ_ENABLE_RX_FIFO_FULL | \ - AML_SDXC_IRQ_ENABLE_A_PKG_CRC_ERR | \ - AML_SDXC_IRQ_ENABLE_A_PKG_TIMEOUT_ERR | \ - AML_SDXC_IRQ_ENABLE_RESP_CRC_ERR | \ - AML_SDXC_IRQ_ENABLE_RESP_TIMEOUT_ERR | \ - AML_SDXC_IRQ_ENABLE_RESP_OK) - -#define AML_SDXC_IRQ_STATUS_REG 40 -#define AML_SDXC_IRQ_STATUS_TX_FIFO_EMPTY (1 << 13) -#define AML_SDXC_IRQ_STATUS_RX_FIFO_FULL (1 << 12) -#define AML_SDXC_IRQ_STATUS_DMA_DONE (1 << 11) -#define AML_SDXC_IRQ_STATUS_TRANSFER_DONE_OK (1 << 7) -#define AML_SDXC_IRQ_STATUS_A_PKG_CRC_ERR (1 << 6) -#define AML_SDXC_IRQ_STATUS_A_PKG_TIMEOUT_ERR (1 << 5) -#define AML_SDXC_IRQ_STATUS_A_PKG_DONE_OK (1 << 4) -#define AML_SDXC_IRQ_STATUS_RESP_CRC_ERR (1 << 2) -#define AML_SDXC_IRQ_STATUS_RESP_TIMEOUT_ERR (1 << 1) -#define AML_SDXC_IRQ_STATUS_RESP_OK (1 << 0) - -#define AML_SDXC_IRQ_STATUS_CLEAR \ - (AML_SDXC_IRQ_STATUS_TX_FIFO_EMPTY | \ - AML_SDXC_IRQ_STATUS_RX_FIFO_FULL | \ - AML_SDXC_IRQ_STATUS_DMA_DONE | \ - AML_SDXC_IRQ_STATUS_TRANSFER_DONE_OK | \ - AML_SDXC_IRQ_STATUS_A_PKG_CRC_ERR | \ - AML_SDXC_IRQ_STATUS_A_PKG_TIMEOUT_ERR | \ - AML_SDXC_IRQ_STATUS_RESP_CRC_ERR | \ - AML_SDXC_IRQ_STATUS_RESP_TIMEOUT_ERR | \ - AML_SDXC_IRQ_STATUS_RESP_OK) - -#define AML_SDXC_SOFT_RESET_REG 44 -#define AML_SDXC_SOFT_RESET_DMA (1 << 5) -#define AML_SDXC_SOFT_RESET_TX_PHY (1 << 4) -#define AML_SDXC_SOFT_RESET_RX_PHY (1 << 3) -#define AML_SDXC_SOFT_RESET_TX_FIFO (1 << 2) -#define AML_SDXC_SOFT_RESET_RX_FIFO (1 << 1) -#define AML_SDXC_SOFT_RESET_MAIN (1 << 0) - -#define AML_SDXC_SOFT_RESET \ - (AML_SDXC_SOFT_RESET_DMA | \ - AML_SDXC_SOFT_RESET_TX_FIFO | \ - AML_SDXC_SOFT_RESET_RX_FIFO | \ - AML_SDXC_SOFT_RESET_MAIN) - -#define AML_SDXC_ENH_CNTRL_REG 52 -#define AML_SDXC_ENH_CNTRL_TX_EMPTY_THOLD_MASK (0x7f << 25) -#define AML_SDXC_ENH_CNTRL_TX_EMPTY_THOLD_SHIFT 25 -#define AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_MASK (0x7f << 18) -#define AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_SHIFT 18 -#define AML_SDXC_ENH_CNTRL_SDIO_IRQ_PERIOD_MASK (0xff << 8) -#define AML_SDXC_ENH_CNTRL_SDIO_IRQ_PERIOD_SHIFT 8 - -#define AML_SDXC_ENH_CNTRL_DMA_NO_WR_RESP_CHECK_M8 (1 << 17) -#define AML_SDXC_ENH_CNTRL_DMA_NO_RD_RESP_CHECK_M8 (1 << 16) -#define AML_SDXC_ENH_CNTRL_RX_TIMEOUT_MASK_M8 (0xff << 0) -#define AML_SDXC_ENH_CNTRL_RX_TIMEOUT_SHIFT_M8 0 - -#define AML_SDXC_ENH_CNTRL_NO_DMA_CHECK_M8M2 (1 << 2) -#define AML_SDXC_ENH_CNTRL_NO_WR_RESP_CHECK_M8M2 (1 << 1) -#define AML_SDXC_ENH_CNTRL_WR_RESP_MODE_SKIP_M8M2 (1 << 0) - -#define AML_SDXC_CLK2_REG 56 -#define AML_SDXC_CLK2_SD_PHASE_MASK (0x3ff << 12) -#define AML_SDXC_CLK2_SD_PHASE_SHIFT 12 -#define AML_SDXC_CLK2_RX_PHASE_MASK (0x3ff << 0) -#define AML_SDXC_CLK2_RX_PHASE_SHIFT 0 - -#endif /* _ARM_AMLOGIC_AML8726_SDXC_M8_H */ Index: head/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c +++ head/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c @@ -1,1395 +0,0 @@ -/*- - * Copyright 2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726-m8 (and later) SDXC host controller driver. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#include "gpio_if.h" -#include "mmcbr_if.h" - -/* - * The table is sorted from highest to lowest and - * last entry in the table is mark by freq == 0. - */ -struct { - uint32_t voltage; - uint32_t freq; - uint32_t rx_phase; -} aml8726_sdxc_clk_phases[] = { - { - MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, - 100000000, - 1 - }, - { - MMC_OCR_320_330 | MMC_OCR_330_340, - 45000000, - 15 - }, - { - MMC_OCR_LOW_VOLTAGE, - 45000000, - 11 - }, - { - MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, - 24999999, - 15 - }, - { - MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, - 5000000, - 23 - }, - { - MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, - 1000000, - 55 - }, - { - MMC_OCR_LOW_VOLTAGE | MMC_OCR_320_330 | MMC_OCR_330_340, - 0, - 1061 - }, -}; - -struct aml8726_sdxc_gpio { - device_t dev; - uint32_t pin; - uint32_t pol; -}; - -struct aml8726_sdxc_softc { - device_t dev; - boolean_t auto_fill_flush; - struct resource *res[2]; - struct mtx mtx; - struct callout ch; - unsigned int ref_freq; - struct aml8726_sdxc_gpio pwr_en; - int voltages[2]; - struct aml8726_sdxc_gpio vselect; - struct aml8726_sdxc_gpio card_rst; - bus_dma_tag_t dmatag; - bus_dmamap_t dmamap; - void *ih_cookie; - struct mmc_host host; - int bus_busy; - struct { - uint32_t time; - uint32_t error; - } busy; - struct mmc_command *cmd; -}; - -static struct resource_spec aml8726_sdxc_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { SYS_RES_IRQ, 0, RF_ACTIVE }, - { -1, 0 } -}; - -#define AML_SDXC_LOCK(sc) mtx_lock(&(sc)->mtx) -#define AML_SDXC_UNLOCK(sc) mtx_unlock(&(sc)->mtx) -#define AML_SDXC_LOCK_ASSERT(sc) mtx_assert(&(sc)->mtx, MA_OWNED) -#define AML_SDXC_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "sdxc", MTX_DEF) -#define AML_SDXC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) -#define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ - (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -#define PIN_ON_FLAG(pol) ((pol) == 0 ? \ - GPIO_PIN_LOW : GPIO_PIN_HIGH) -#define PIN_OFF_FLAG(pol) ((pol) == 0 ? \ - GPIO_PIN_HIGH : GPIO_PIN_LOW) - -#define msecs_to_ticks(ms) (((ms)*hz)/1000 + 1) - -static void aml8726_sdxc_timeout(void *arg); - -static void -aml8726_sdxc_mapmem(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - bus_addr_t *busaddrp; - - /* - * There should only be one bus space address since - * bus_dma_tag_create was called with nsegments = 1. - */ - - busaddrp = (bus_addr_t *)arg; - *busaddrp = segs->ds_addr; -} - -static int -aml8726_sdxc_power_off(struct aml8726_sdxc_softc *sc) -{ - - if (sc->pwr_en.dev == NULL) - return (0); - - return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, - PIN_OFF_FLAG(sc->pwr_en.pol))); -} - -static int -aml8726_sdxc_power_on(struct aml8726_sdxc_softc *sc) -{ - - if (sc->pwr_en.dev == NULL) - return (0); - - return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin, - PIN_ON_FLAG(sc->pwr_en.pol))); -} - -static void -aml8726_sdxc_soft_reset(struct aml8726_sdxc_softc *sc) -{ - - CSR_WRITE_4(sc, AML_SDXC_SOFT_RESET_REG, AML_SDXC_SOFT_RESET); - CSR_BARRIER(sc, AML_SDXC_SOFT_RESET_REG); - DELAY(5); -} - -static void -aml8726_sdxc_engage_dma(struct aml8726_sdxc_softc *sc) -{ - int i; - uint32_t pdmar; - uint32_t sr; - struct mmc_data *data; - - data = sc->cmd->data; - - if (data == NULL || data->len == 0) - return; - - /* - * Engaging the DMA hardware is recommended before writing - * to AML_SDXC_SEND_REG so that the FIFOs are ready to go. - * - * Presumably AML_SDXC_CNTRL_REG and AML_SDXC_DMA_ADDR_REG - * must be set up prior to this happening. - */ - - pdmar = CSR_READ_4(sc, AML_SDXC_PDMA_REG); - - pdmar &= ~AML_SDXC_PDMA_RX_FLUSH_MODE_SW; - pdmar |= AML_SDXC_PDMA_DMA_EN; - - if (sc->auto_fill_flush == true) { - CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); - CSR_BARRIER(sc, AML_SDXC_PDMA_REG); - return; - } - - if ((data->flags & MMC_DATA_READ) != 0) { - pdmar |= AML_SDXC_PDMA_RX_FLUSH_MODE_SW; - CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); - CSR_BARRIER(sc, AML_SDXC_PDMA_REG); - } else { - pdmar |= AML_SDXC_PDMA_TX_FILL; - CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); - CSR_BARRIER(sc, AML_SDXC_PDMA_REG); - - /* - * Wait up to 100us for data to show up. - */ - for (i = 0; i < 100; i++) { - sr = CSR_READ_4(sc, AML_SDXC_STATUS_REG); - if ((sr & AML_SDXC_STATUS_TX_CNT_MASK) != 0) - break; - DELAY(1); - } - if (i >= 100) - device_printf(sc->dev, "TX FIFO fill timeout\n"); - } -} - -static void -aml8726_sdxc_disengage_dma(struct aml8726_sdxc_softc *sc) -{ - int i; - uint32_t pdmar; - uint32_t sr; - struct mmc_data *data; - - data = sc->cmd->data; - - if (data == NULL || data->len == 0) - return; - - pdmar = CSR_READ_4(sc, AML_SDXC_PDMA_REG); - - if (sc->auto_fill_flush == true) { - pdmar &= ~AML_SDXC_PDMA_DMA_EN; - CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); - CSR_BARRIER(sc, AML_SDXC_PDMA_REG); - return; - } - - if ((data->flags & MMC_DATA_READ) != 0) { - pdmar |= AML_SDXC_PDMA_RX_FLUSH_NOW; - CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); - CSR_BARRIER(sc, AML_SDXC_PDMA_REG); - - /* - * Wait up to 100us for data to drain. - */ - for (i = 0; i < 100; i++) { - sr = CSR_READ_4(sc, AML_SDXC_STATUS_REG); - if ((sr & AML_SDXC_STATUS_RX_CNT_MASK) == 0) - break; - DELAY(1); - } - if (i >= 100) - device_printf(sc->dev, "RX FIFO drain timeout\n"); - } - - pdmar &= ~(AML_SDXC_PDMA_DMA_EN | AML_SDXC_PDMA_RX_FLUSH_MODE_SW); - - CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); - CSR_BARRIER(sc, AML_SDXC_PDMA_REG); -} - -static int -aml8726_sdxc_start_command(struct aml8726_sdxc_softc *sc, - struct mmc_command *cmd) -{ - bus_addr_t baddr; - uint32_t block_size; - uint32_t ctlr; - uint32_t ier; - uint32_t sndr; - uint32_t timeout; - int error; - struct mmc_data *data; - - AML_SDXC_LOCK_ASSERT(sc); - - if (cmd->opcode > 0x3f) - return (MMC_ERR_INVALID); - - /* - * Ensure the hardware state machine is in a known state. - */ - aml8726_sdxc_soft_reset(sc); - - sndr = cmd->opcode; - - if ((cmd->flags & MMC_RSP_136) != 0) { - sndr |= AML_SDXC_SEND_CMD_HAS_RESP; - sndr |= AML_SDXC_SEND_RESP_136; - /* - * According to the SD spec the 136 bit response is - * used for getting the CID or CSD in which case the - * CRC7 is embedded in the contents rather than being - * calculated over the entire response (the controller - * always checks the CRC7 over the entire response). - */ - sndr |= AML_SDXC_SEND_RESP_NO_CRC7_CHECK; - } else if ((cmd->flags & MMC_RSP_PRESENT) != 0) - sndr |= AML_SDXC_SEND_CMD_HAS_RESP; - - if ((cmd->flags & MMC_RSP_CRC) == 0) - sndr |= AML_SDXC_SEND_RESP_NO_CRC7_CHECK; - - if (cmd->opcode == MMC_STOP_TRANSMISSION) - sndr |= AML_SDXC_SEND_DATA_STOP; - - data = cmd->data; - - baddr = 0; - ctlr = CSR_READ_4(sc, AML_SDXC_CNTRL_REG); - ier = AML_SDXC_IRQ_ENABLE_STANDARD; - timeout = AML_SDXC_CMD_TIMEOUT; - - ctlr &= ~AML_SDXC_CNTRL_PKG_LEN_MASK; - - if (data && data->len && - (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) { - block_size = data->len; - - if ((data->flags & MMC_DATA_MULTI) != 0) { - block_size = MMC_SECTOR_SIZE; - if ((data->len % block_size) != 0) - return (MMC_ERR_INVALID); - } - - if (block_size > 512) - return (MMC_ERR_INVALID); - - sndr |= AML_SDXC_SEND_CMD_HAS_DATA; - sndr |= ((data->flags & MMC_DATA_WRITE) != 0) ? - AML_SDXC_SEND_DATA_WRITE : 0; - sndr |= (((data->len / block_size) - 1) << - AML_SDXC_SEND_REP_PKG_CNT_SHIFT); - - ctlr |= ((block_size < 512) ? block_size : 0) << - AML_SDXC_CNTRL_PKG_LEN_SHIFT; - - ier &= ~AML_SDXC_IRQ_ENABLE_RESP_OK; - ier |= (sc->auto_fill_flush == true || - (data->flags & MMC_DATA_WRITE) != 0) ? - AML_SDXC_IRQ_ENABLE_DMA_DONE : - AML_SDXC_IRQ_ENABLE_TRANSFER_DONE_OK; - - error = bus_dmamap_load(sc->dmatag, sc->dmamap, - data->data, data->len, aml8726_sdxc_mapmem, &baddr, - BUS_DMA_NOWAIT); - if (error) - return (MMC_ERR_NO_MEMORY); - - if ((data->flags & MMC_DATA_READ) != 0) { - bus_dmamap_sync(sc->dmatag, sc->dmamap, - BUS_DMASYNC_PREREAD); - timeout = AML_SDXC_READ_TIMEOUT * - (data->len / block_size); - } else { - bus_dmamap_sync(sc->dmatag, sc->dmamap, - BUS_DMASYNC_PREWRITE); - timeout = AML_SDXC_WRITE_TIMEOUT * - (data->len / block_size); - } - } - - sc->cmd = cmd; - - cmd->error = MMC_ERR_NONE; - - sc->busy.time = 0; - sc->busy.error = MMC_ERR_NONE; - - if (timeout > AML_SDXC_MAX_TIMEOUT) - timeout = AML_SDXC_MAX_TIMEOUT; - - callout_reset(&sc->ch, msecs_to_ticks(timeout), - aml8726_sdxc_timeout, sc); - - CSR_WRITE_4(sc, AML_SDXC_IRQ_ENABLE_REG, ier); - - CSR_WRITE_4(sc, AML_SDXC_CNTRL_REG, ctlr); - CSR_WRITE_4(sc, AML_SDXC_DMA_ADDR_REG, (uint32_t)baddr); - CSR_WRITE_4(sc, AML_SDXC_CMD_ARGUMENT_REG, cmd->arg); - - aml8726_sdxc_engage_dma(sc); - - CSR_WRITE_4(sc, AML_SDXC_SEND_REG, sndr); - CSR_BARRIER(sc, AML_SDXC_SEND_REG); - - return (MMC_ERR_NONE); -} - -static void -aml8726_sdxc_finish_command(struct aml8726_sdxc_softc *sc, int mmc_error) -{ - int mmc_stop_error; - struct mmc_command *cmd; - struct mmc_command *stop_cmd; - struct mmc_data *data; - - AML_SDXC_LOCK_ASSERT(sc); - - /* Clear all interrupts since the request is no longer in flight. */ - CSR_WRITE_4(sc, AML_SDXC_IRQ_STATUS_REG, AML_SDXC_IRQ_STATUS_CLEAR); - CSR_BARRIER(sc, AML_SDXC_IRQ_STATUS_REG); - - /* In some cases (e.g. finish called via timeout) this is a NOP. */ - callout_stop(&sc->ch); - - cmd = sc->cmd; - sc->cmd = NULL; - - cmd->error = mmc_error; - - data = cmd->data; - - if (data && data->len - && (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) { - if ((data->flags & MMC_DATA_READ) != 0) - bus_dmamap_sync(sc->dmatag, sc->dmamap, - BUS_DMASYNC_POSTREAD); - else - bus_dmamap_sync(sc->dmatag, sc->dmamap, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->dmatag, sc->dmamap); - } - - /* - * If there's a linked stop command, then start the stop command. - * In order to establish a known state attempt the stop command - * even if the original request encountered an error. - */ - - stop_cmd = (cmd->mrq->stop != cmd) ? cmd->mrq->stop : NULL; - - if (stop_cmd != NULL) { - /* - * If the original command executed successfully, then - * the hardware will also have automatically executed - * a stop command so don't bother with the one supplied - * with the original request. - */ - - if (mmc_error == MMC_ERR_NONE) { - stop_cmd->error = MMC_ERR_NONE; - stop_cmd->resp[0] = cmd->resp[0]; - stop_cmd->resp[1] = cmd->resp[1]; - stop_cmd->resp[2] = cmd->resp[2]; - stop_cmd->resp[3] = cmd->resp[3]; - } else { - mmc_stop_error = aml8726_sdxc_start_command(sc, - stop_cmd); - if (mmc_stop_error == MMC_ERR_NONE) { - AML_SDXC_UNLOCK(sc); - return; - } - stop_cmd->error = mmc_stop_error; - } - } - - AML_SDXC_UNLOCK(sc); - - /* Execute the callback after dropping the lock. */ - if (cmd->mrq != NULL) - cmd->mrq->done(cmd->mrq); -} - -static void -aml8726_sdxc_timeout(void *arg) -{ - struct aml8726_sdxc_softc *sc = (struct aml8726_sdxc_softc *)arg; - - /* - * The command failed to complete in time so forcefully - * terminate it. - */ - aml8726_sdxc_soft_reset(sc); - - /* - * Ensure the command has terminated before continuing on - * to things such as bus_dmamap_sync / bus_dmamap_unload. - */ - while ((CSR_READ_4(sc, AML_SDXC_STATUS_REG) & - AML_SDXC_STATUS_BUSY) != 0) - cpu_spinwait(); - - aml8726_sdxc_finish_command(sc, MMC_ERR_TIMEOUT); -} - -static void -aml8726_sdxc_busy_check(void *arg) -{ - struct aml8726_sdxc_softc *sc = (struct aml8726_sdxc_softc *)arg; - uint32_t sr; - - sc->busy.time += AML_SDXC_BUSY_POLL_INTVL; - - sr = CSR_READ_4(sc, AML_SDXC_STATUS_REG); - - if ((sr & AML_SDXC_STATUS_DAT0) == 0) { - if (sc->busy.time < AML_SDXC_BUSY_TIMEOUT) { - callout_reset(&sc->ch, - msecs_to_ticks(AML_SDXC_BUSY_POLL_INTVL), - aml8726_sdxc_busy_check, sc); - AML_SDXC_UNLOCK(sc); - return; - } - if (sc->busy.error == MMC_ERR_NONE) - sc->busy.error = MMC_ERR_TIMEOUT; - } - - aml8726_sdxc_finish_command(sc, sc->busy.error); -} - -static void -aml8726_sdxc_intr(void *arg) -{ - struct aml8726_sdxc_softc *sc = (struct aml8726_sdxc_softc *)arg; - uint32_t isr; - uint32_t pdmar; - uint32_t sndr; - uint32_t sr; - int i; - int mmc_error; - int start; - int stop; - - AML_SDXC_LOCK(sc); - - isr = CSR_READ_4(sc, AML_SDXC_IRQ_STATUS_REG); - sndr = CSR_READ_4(sc, AML_SDXC_SEND_REG); - sr = CSR_READ_4(sc, AML_SDXC_STATUS_REG); - - if (sc->cmd == NULL) - goto spurious; - - mmc_error = MMC_ERR_NONE; - - if ((isr & (AML_SDXC_IRQ_STATUS_TX_FIFO_EMPTY | - AML_SDXC_IRQ_STATUS_RX_FIFO_FULL)) != 0) - mmc_error = MMC_ERR_FIFO; - else if ((isr & (AML_SDXC_IRQ_ENABLE_A_PKG_CRC_ERR | - AML_SDXC_IRQ_ENABLE_RESP_CRC_ERR)) != 0) - mmc_error = MMC_ERR_BADCRC; - else if ((isr & (AML_SDXC_IRQ_ENABLE_A_PKG_TIMEOUT_ERR | - AML_SDXC_IRQ_ENABLE_RESP_TIMEOUT_ERR)) != 0) - mmc_error = MMC_ERR_TIMEOUT; - else if ((isr & (AML_SDXC_IRQ_STATUS_RESP_OK | - AML_SDXC_IRQ_STATUS_DMA_DONE | - AML_SDXC_IRQ_STATUS_TRANSFER_DONE_OK)) != 0) { - ; - } - else { -spurious: - /* - * Clear spurious interrupts while leaving intacted any - * interrupts that may have occurred after we read the - * interrupt status register. - */ - - CSR_WRITE_4(sc, AML_SDXC_IRQ_STATUS_REG, - (AML_SDXC_IRQ_STATUS_CLEAR & isr)); - CSR_BARRIER(sc, AML_SDXC_IRQ_STATUS_REG); - AML_SDXC_UNLOCK(sc); - return; - } - - aml8726_sdxc_disengage_dma(sc); - - if ((sndr & AML_SDXC_SEND_CMD_HAS_RESP) != 0) { - start = 0; - stop = 1; - if ((sndr & AML_SDXC_SEND_RESP_136) != 0) { - start = 1; - stop = start + 4; - } - for (i = start; i < stop; i++) { - pdmar = CSR_READ_4(sc, AML_SDXC_PDMA_REG); - pdmar &= ~(AML_SDXC_PDMA_DMA_EN | - AML_SDXC_PDMA_RESP_INDEX_MASK); - pdmar |= i << AML_SDXC_PDMA_RESP_INDEX_SHIFT; - CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); - sc->cmd->resp[(stop - 1) - i] = CSR_READ_4(sc, - AML_SDXC_CMD_ARGUMENT_REG); - } - } - - if ((sr & AML_SDXC_STATUS_BUSY) != 0 && - /* - * A multiblock operation may keep the hardware - * busy until stop transmission is executed. - */ - (isr & (AML_SDXC_IRQ_STATUS_DMA_DONE | - AML_SDXC_IRQ_STATUS_TRANSFER_DONE_OK)) == 0) { - if (mmc_error == MMC_ERR_NONE) - mmc_error = MMC_ERR_FAILED; - - /* - * Issue a soft reset to terminate the command. - * - * Ensure the command has terminated before continuing on - * to things such as bus_dmamap_sync / bus_dmamap_unload. - */ - - aml8726_sdxc_soft_reset(sc); - - while ((CSR_READ_4(sc, AML_SDXC_STATUS_REG) & - AML_SDXC_STATUS_BUSY) != 0) - cpu_spinwait(); - } - - /* - * The stop command can be generated either manually or - * automatically by the hardware if MISC_MANUAL_STOP_MODE - * has not been set. In either case check for busy. - */ - - if (((sc->cmd->flags & MMC_RSP_BUSY) != 0 || - (sndr & AML_SDXC_SEND_INDEX_MASK) == MMC_STOP_TRANSMISSION) && - (sr & AML_SDXC_STATUS_DAT0) == 0) { - sc->busy.error = mmc_error; - callout_reset(&sc->ch, - msecs_to_ticks(AML_SDXC_BUSY_POLL_INTVL), - aml8726_sdxc_busy_check, sc); - CSR_WRITE_4(sc, AML_SDXC_IRQ_STATUS_REG, - (AML_SDXC_IRQ_STATUS_CLEAR & isr)); - CSR_BARRIER(sc, AML_SDXC_IRQ_STATUS_REG); - AML_SDXC_UNLOCK(sc); - return; - } - - aml8726_sdxc_finish_command(sc, mmc_error); -} - -static int -aml8726_sdxc_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-sdxc-m8")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726-m8 SDXC"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_sdxc_attach(device_t dev) -{ - struct aml8726_sdxc_softc *sc = device_get_softc(dev); - char *voltages; - char *voltage; - int error; - int nvoltages; - pcell_t prop[3]; - phandle_t node; - ssize_t len; - device_t child; - uint32_t ectlr; - uint32_t miscr; - uint32_t pdmar; - - sc->dev = dev; - - sc->auto_fill_flush = false; - - pdmar = AML_SDXC_PDMA_DMA_URGENT | - (49 << AML_SDXC_PDMA_TX_THOLD_SHIFT) | - (7 << AML_SDXC_PDMA_RX_THOLD_SHIFT) | - (15 << AML_SDXC_PDMA_RD_BURST_SHIFT) | - (7 << AML_SDXC_PDMA_WR_BURST_SHIFT); - - miscr = (2 << AML_SDXC_MISC_WCRC_OK_PAT_SHIFT) | - (5 << AML_SDXC_MISC_WCRC_ERR_PAT_SHIFT); - - ectlr = (12 << AML_SDXC_ENH_CNTRL_SDIO_IRQ_PERIOD_SHIFT); - - /* - * Certain bitfields are dependent on the hardware revision. - */ - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M8: - switch (aml8726_soc_metal_rev) { - case AML_SOC_M8_METAL_REV_M2_A: - sc->auto_fill_flush = true; - miscr |= (6 << AML_SDXC_MISC_TXSTART_THOLD_SHIFT); - ectlr |= (64 << AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_SHIFT) | - AML_SDXC_ENH_CNTRL_WR_RESP_MODE_SKIP_M8M2; - break; - default: - miscr |= (7 << AML_SDXC_MISC_TXSTART_THOLD_SHIFT); - ectlr |= (63 << AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_SHIFT) | - AML_SDXC_ENH_CNTRL_DMA_NO_WR_RESP_CHECK_M8 | - (255 << AML_SDXC_ENH_CNTRL_RX_TIMEOUT_SHIFT_M8); - - break; - } - break; - case AML_SOC_HW_REV_M8B: - miscr |= (7 << AML_SDXC_MISC_TXSTART_THOLD_SHIFT); - ectlr |= (63 << AML_SDXC_ENH_CNTRL_RX_FULL_THOLD_SHIFT) | - AML_SDXC_ENH_CNTRL_DMA_NO_WR_RESP_CHECK_M8 | - (255 << AML_SDXC_ENH_CNTRL_RX_TIMEOUT_SHIFT_M8); - break; - default: - device_printf(dev, "unsupported SoC\n"); - return (ENXIO); - /* NOTREACHED */ - } - - node = ofw_bus_get_node(dev); - - len = OF_getencprop(node, "clock-frequency", prop, sizeof(prop)); - if ((len / sizeof(prop[0])) != 1 || prop[0] == 0) { - device_printf(dev, - "missing clock-frequency attribute in FDT\n"); - return (ENXIO); - } - - sc->ref_freq = prop[0]; - - sc->pwr_en.dev = NULL; - - len = OF_getencprop(node, "mmc-pwr-en", prop, sizeof(prop)); - if (len > 0) { - if ((len / sizeof(prop[0])) == 3) { - sc->pwr_en.dev = OF_device_from_xref(prop[0]); - sc->pwr_en.pin = prop[1]; - sc->pwr_en.pol = prop[2]; - } - - if (sc->pwr_en.dev == NULL) { - device_printf(dev, - "unable to process mmc-pwr-en attribute in FDT\n"); - return (ENXIO); - } - - /* Turn off power and then configure the output driver. */ - if (aml8726_sdxc_power_off(sc) != 0 || - GPIO_PIN_SETFLAGS(sc->pwr_en.dev, sc->pwr_en.pin, - GPIO_PIN_OUTPUT) != 0) { - device_printf(dev, - "could not use gpio to control power\n"); - return (ENXIO); - } - } - - len = OF_getprop_alloc(node, "mmc-voltages", - (void **)&voltages); - - if (len < 0) { - device_printf(dev, "missing mmc-voltages attribute in FDT\n"); - return (ENXIO); - } - - sc->voltages[0] = 0; - sc->voltages[1] = 0; - - voltage = voltages; - nvoltages = 0; - - while (len && nvoltages < 2) { - if (strncmp("1.8", voltage, len) == 0) - sc->voltages[nvoltages] = MMC_OCR_LOW_VOLTAGE; - else if (strncmp("3.3", voltage, len) == 0) - sc->voltages[nvoltages] = MMC_OCR_320_330 | - MMC_OCR_330_340; - else { - device_printf(dev, - "unknown voltage attribute %.*s in FDT\n", - len, voltage); - OF_prop_free(voltages); - return (ENXIO); - } - - nvoltages++; - - /* queue up next string */ - while (*voltage && len) { - voltage++; - len--; - } - if (len) { - voltage++; - len--; - } - } - - OF_prop_free(voltages); - - sc->vselect.dev = NULL; - - len = OF_getencprop(node, "mmc-vselect", prop, sizeof(prop)); - if (len > 0) { - if ((len / sizeof(prop[0])) == 2) { - sc->vselect.dev = OF_device_from_xref(prop[0]); - sc->vselect.pin = prop[1]; - sc->vselect.pol = 1; - } - - if (sc->vselect.dev == NULL) { - device_printf(dev, - "unable to process mmc-vselect attribute in FDT\n"); - return (ENXIO); - } - - /* - * With the power off select voltage 0 and then - * configure the output driver. - */ - if (GPIO_PIN_SET(sc->vselect.dev, sc->vselect.pin, 0) != 0 || - GPIO_PIN_SETFLAGS(sc->vselect.dev, sc->vselect.pin, - GPIO_PIN_OUTPUT) != 0) { - device_printf(dev, - "could not use gpio to set voltage\n"); - return (ENXIO); - } - } - - if (nvoltages == 0) { - device_printf(dev, "no voltages in FDT\n"); - return (ENXIO); - } else if (nvoltages == 1 && sc->vselect.dev != NULL) { - device_printf(dev, "only one voltage in FDT\n"); - return (ENXIO); - } else if (nvoltages == 2 && sc->vselect.dev == NULL) { - device_printf(dev, "too many voltages in FDT\n"); - return (ENXIO); - } - - sc->card_rst.dev = NULL; - - len = OF_getencprop(node, "mmc-rst", prop, sizeof(prop)); - if (len > 0) { - if ((len / sizeof(prop[0])) == 3) { - sc->card_rst.dev = OF_device_from_xref(prop[0]); - sc->card_rst.pin = prop[1]; - sc->card_rst.pol = prop[2]; - } - - if (sc->card_rst.dev == NULL) { - device_printf(dev, - "unable to process mmc-rst attribute in FDT\n"); - return (ENXIO); - } - } - - if (bus_alloc_resources(dev, aml8726_sdxc_spec, sc->res)) { - device_printf(dev, "could not allocate resources for device\n"); - return (ENXIO); - } - - AML_SDXC_LOCK_INIT(sc); - - error = bus_dma_tag_create(bus_get_dma_tag(dev), AML_SDXC_ALIGN_DMA, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - AML_SDXC_MAX_DMA, 1, AML_SDXC_MAX_DMA, 0, NULL, NULL, &sc->dmatag); - if (error) - goto fail; - - error = bus_dmamap_create(sc->dmatag, 0, &sc->dmamap); - - if (error) - goto fail; - - error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE, - NULL, aml8726_sdxc_intr, sc, &sc->ih_cookie); - if (error) { - device_printf(dev, "could not setup interrupt handler\n"); - goto fail; - } - - callout_init_mtx(&sc->ch, &sc->mtx, CALLOUT_RETURNUNLOCKED); - - sc->host.f_min = 200000; - sc->host.f_max = 100000000; - sc->host.host_ocr = sc->voltages[0] | sc->voltages[1]; - sc->host.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA | - MMC_CAP_HSPEED; - - aml8726_sdxc_soft_reset(sc); - - CSR_WRITE_4(sc, AML_SDXC_PDMA_REG, pdmar); - - CSR_WRITE_4(sc, AML_SDXC_MISC_REG, miscr); - - CSR_WRITE_4(sc, AML_SDXC_ENH_CNTRL_REG, ectlr); - - child = device_add_child(dev, "mmc", -1); - - if (!child) { - device_printf(dev, "could not add mmc\n"); - error = ENXIO; - goto fail; - } - - error = device_probe_and_attach(child); - - if (error) { - device_printf(dev, "could not attach mmc\n"); - goto fail; - } - - return (0); - -fail: - if (sc->ih_cookie) - bus_teardown_intr(dev, sc->res[1], sc->ih_cookie); - - if (sc->dmamap) - bus_dmamap_destroy(sc->dmatag, sc->dmamap); - - if (sc->dmatag) - bus_dma_tag_destroy(sc->dmatag); - - AML_SDXC_LOCK_DESTROY(sc); - - (void)aml8726_sdxc_power_off(sc); - - bus_release_resources(dev, aml8726_sdxc_spec, sc->res); - - return (error); -} - -static int -aml8726_sdxc_detach(device_t dev) -{ - struct aml8726_sdxc_softc *sc = device_get_softc(dev); - - AML_SDXC_LOCK(sc); - - if (sc->cmd != NULL) { - AML_SDXC_UNLOCK(sc); - return (EBUSY); - } - - /* - * Turn off the power, reset the hardware state machine, - * and disable the interrupts. - */ - aml8726_sdxc_power_off(sc); - aml8726_sdxc_soft_reset(sc); - CSR_WRITE_4(sc, AML_SDXC_IRQ_ENABLE_REG, 0); - - AML_SDXC_UNLOCK(sc); - - bus_generic_detach(dev); - - bus_teardown_intr(dev, sc->res[1], sc->ih_cookie); - - bus_dmamap_destroy(sc->dmatag, sc->dmamap); - - bus_dma_tag_destroy(sc->dmatag); - - AML_SDXC_LOCK_DESTROY(sc); - - bus_release_resources(dev, aml8726_sdxc_spec, sc->res); - - return (0); -} - -static int -aml8726_sdxc_shutdown(device_t dev) -{ - struct aml8726_sdxc_softc *sc = device_get_softc(dev); - - /* - * Turn off the power, reset the hardware state machine, - * and disable the interrupts. - */ - aml8726_sdxc_power_off(sc); - aml8726_sdxc_soft_reset(sc); - CSR_WRITE_4(sc, AML_SDXC_IRQ_ENABLE_REG, 0); - - return (0); -} - -static int -aml8726_sdxc_update_ios(device_t bus, device_t child) -{ - struct aml8726_sdxc_softc *sc = device_get_softc(bus); - struct mmc_ios *ios = &sc->host.ios; - unsigned int divisor; - int error; - int i; - uint32_t cctlr; - uint32_t clk2r; - uint32_t ctlr; - uint32_t freq; - - ctlr = (7 << AML_SDXC_CNTRL_TX_ENDIAN_SHIFT) | - (7 << AML_SDXC_CNTRL_RX_ENDIAN_SHIFT) | - (0xf << AML_SDXC_CNTRL_RX_PERIOD_SHIFT) | - (0x7f << AML_SDXC_CNTRL_RX_TIMEOUT_SHIFT); - - switch (ios->bus_width) { - case bus_width_8: - ctlr |= AML_SDXC_CNTRL_BUS_WIDTH_8; - break; - case bus_width_4: - ctlr |= AML_SDXC_CNTRL_BUS_WIDTH_4; - break; - case bus_width_1: - ctlr |= AML_SDXC_CNTRL_BUS_WIDTH_1; - break; - default: - return (EINVAL); - } - - CSR_WRITE_4(sc, AML_SDXC_CNTRL_REG, ctlr); - - /* - * Disable clocks and then clock module prior to setting desired values. - */ - cctlr = CSR_READ_4(sc, AML_SDXC_CLK_CNTRL_REG); - cctlr &= ~(AML_SDXC_CLK_CNTRL_TX_CLK_EN | AML_SDXC_CLK_CNTRL_RX_CLK_EN | - AML_SDXC_CLK_CNTRL_SD_CLK_EN); - CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); - CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); - cctlr &= ~AML_SDXC_CLK_CNTRL_CLK_MODULE_EN; - CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); - CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); - - /* - * aml8726-m8 - * - * Clock select 1 fclk_div2 (1.275 GHz) - */ - cctlr &= ~AML_SDXC_CLK_CNTRL_CLK_SEL_MASK; - cctlr |= (1 << AML_SDXC_CLK_CNTRL_CLK_SEL_SHIFT); - - divisor = sc->ref_freq / ios->clock - 1; - if (divisor == 0 || divisor == -1) - divisor = 1; - if ((sc->ref_freq / (divisor + 1)) > ios->clock) - divisor += 1; - if (divisor > (AML_SDXC_CLK_CNTRL_CLK_DIV_MASK >> - AML_SDXC_CLK_CNTRL_CLK_DIV_SHIFT)) - divisor = AML_SDXC_CLK_CNTRL_CLK_DIV_MASK >> - AML_SDXC_CLK_CNTRL_CLK_DIV_SHIFT; - - cctlr &= ~AML_SDXC_CLK_CNTRL_CLK_DIV_MASK; - cctlr |= divisor << AML_SDXC_CLK_CNTRL_CLK_DIV_SHIFT; - - cctlr &= ~AML_SDXC_CLK_CNTRL_MEM_PWR_MASK; - cctlr |= AML_SDXC_CLK_CNTRL_MEM_PWR_ON; - - CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); - CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); - - /* - * Enable clock module and then clocks after setting desired values. - */ - cctlr |= AML_SDXC_CLK_CNTRL_CLK_MODULE_EN; - CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); - CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); - cctlr |= AML_SDXC_CLK_CNTRL_TX_CLK_EN | AML_SDXC_CLK_CNTRL_RX_CLK_EN | - AML_SDXC_CLK_CNTRL_SD_CLK_EN; - CSR_WRITE_4(sc, AML_SDXC_CLK_CNTRL_REG, cctlr); - CSR_BARRIER(sc, AML_SDXC_CLK_CNTRL_REG); - - freq = sc->ref_freq / divisor; - - for (i = 0; aml8726_sdxc_clk_phases[i].voltage; i++) { - if ((aml8726_sdxc_clk_phases[i].voltage & - (1 << ios->vdd)) != 0 && - freq > aml8726_sdxc_clk_phases[i].freq) - break; - if (aml8726_sdxc_clk_phases[i].freq == 0) - break; - } - - clk2r = (1 << AML_SDXC_CLK2_SD_PHASE_SHIFT) | - (aml8726_sdxc_clk_phases[i].rx_phase << - AML_SDXC_CLK2_RX_PHASE_SHIFT); - CSR_WRITE_4(sc, AML_SDXC_CLK2_REG, clk2r); - CSR_BARRIER(sc, AML_SDXC_CLK2_REG); - - error = 0; - - switch (ios->power_mode) { - case power_up: - /* - * Configure and power on the regulator so that the - * voltage stabilizes prior to powering on the card. - */ - if (sc->vselect.dev != NULL) { - for (i = 0; i < 2; i++) - if ((sc->voltages[i] & (1 << ios->vdd)) != 0) - break; - if (i >= 2) - return (EINVAL); - error = GPIO_PIN_SET(sc->vselect.dev, - sc->vselect.pin, i); - } - break; - case power_on: - error = aml8726_sdxc_power_on(sc); - if (error) - break; - - if (sc->card_rst.dev != NULL) { - if (GPIO_PIN_SET(sc->card_rst.dev, sc->card_rst.pin, - PIN_ON_FLAG(sc->card_rst.pol)) != 0 || - GPIO_PIN_SETFLAGS(sc->card_rst.dev, - sc->card_rst.pin, - GPIO_PIN_OUTPUT) != 0) - error = ENXIO; - - DELAY(5); - - if (GPIO_PIN_SET(sc->card_rst.dev, sc->card_rst.pin, - PIN_OFF_FLAG(sc->card_rst.pol)) != 0) - error = ENXIO; - - DELAY(5); - - if (error) { - device_printf(sc->dev, - "could not use gpio to reset card\n"); - break; - } - } - break; - case power_off: - error = aml8726_sdxc_power_off(sc); - break; - default: - return (EINVAL); - } - - return (error); -} - -static int -aml8726_sdxc_request(device_t bus, device_t child, struct mmc_request *req) -{ - struct aml8726_sdxc_softc *sc = device_get_softc(bus); - int mmc_error; - - AML_SDXC_LOCK(sc); - - if (sc->cmd != NULL) { - AML_SDXC_UNLOCK(sc); - return (EBUSY); - } - - mmc_error = aml8726_sdxc_start_command(sc, req->cmd); - - AML_SDXC_UNLOCK(sc); - - /* Execute the callback after dropping the lock. */ - if (mmc_error != MMC_ERR_NONE) { - req->cmd->error = mmc_error; - req->done(req); - } - - return (0); -} - -static int -aml8726_sdxc_read_ivar(device_t bus, device_t child, - int which, uintptr_t *result) -{ - struct aml8726_sdxc_softc *sc = device_get_softc(bus); - - switch (which) { - case MMCBR_IVAR_BUS_MODE: - *(int *)result = sc->host.ios.bus_mode; - break; - case MMCBR_IVAR_BUS_WIDTH: - *(int *)result = sc->host.ios.bus_width; - break; - case MMCBR_IVAR_CHIP_SELECT: - *(int *)result = sc->host.ios.chip_select; - break; - case MMCBR_IVAR_CLOCK: - *(int *)result = sc->host.ios.clock; - break; - case MMCBR_IVAR_F_MIN: - *(int *)result = sc->host.f_min; - break; - case MMCBR_IVAR_F_MAX: - *(int *)result = sc->host.f_max; - break; - case MMCBR_IVAR_HOST_OCR: - *(int *)result = sc->host.host_ocr; - break; - case MMCBR_IVAR_MODE: - *(int *)result = sc->host.mode; - break; - case MMCBR_IVAR_OCR: - *(int *)result = sc->host.ocr; - break; - case MMCBR_IVAR_POWER_MODE: - *(int *)result = sc->host.ios.power_mode; - break; - case MMCBR_IVAR_RETUNE_REQ: - *(int *)result = return_req_none; - break; - case MMCBR_IVAR_VDD: - *(int *)result = sc->host.ios.vdd; - break; - case MMCBR_IVAR_VCCQ: - *result = sc->host.ios.vccq; - break; - case MMCBR_IVAR_CAPS: - *(int *)result = sc->host.caps; - break; - case MMCBR_IVAR_TIMING: - *(int *)result = sc->host.ios.timing; - break; - case MMCBR_IVAR_MAX_DATA: - *(int *)result = AML_SDXC_MAX_DMA / MMC_SECTOR_SIZE; - break; - case MMCBR_IVAR_MAX_BUSY_TIMEOUT: - *(int *)result = 1000000; /* 1s max */ - break; - default: - return (EINVAL); - } - - return (0); -} - -static int -aml8726_sdxc_write_ivar(device_t bus, device_t child, - int which, uintptr_t value) -{ - struct aml8726_sdxc_softc *sc = device_get_softc(bus); - - switch (which) { - case MMCBR_IVAR_BUS_MODE: - sc->host.ios.bus_mode = value; - break; - case MMCBR_IVAR_BUS_WIDTH: - sc->host.ios.bus_width = value; - break; - case MMCBR_IVAR_CHIP_SELECT: - sc->host.ios.chip_select = value; - break; - case MMCBR_IVAR_CLOCK: - sc->host.ios.clock = value; - break; - case MMCBR_IVAR_MODE: - sc->host.mode = value; - break; - case MMCBR_IVAR_OCR: - sc->host.ocr = value; - break; - case MMCBR_IVAR_POWER_MODE: - sc->host.ios.power_mode = value; - break; - case MMCBR_IVAR_VDD: - sc->host.ios.vdd = value; - break; - case MMCBR_IVAR_VCCQ: - sc->host.ios.vccq = value; - break; - case MMCBR_IVAR_TIMING: - sc->host.ios.timing = value; - break; - /* These are read-only */ - case MMCBR_IVAR_CAPS: - case MMCBR_IVAR_HOST_OCR: - case MMCBR_IVAR_F_MIN: - case MMCBR_IVAR_F_MAX: - case MMCBR_IVAR_MAX_DATA: - default: - return (EINVAL); - } - - return (0); -} - -static int -aml8726_sdxc_get_ro(device_t bus, device_t child) -{ - - return (0); -} - -static int -aml8726_sdxc_acquire_host(device_t bus, device_t child) -{ - struct aml8726_sdxc_softc *sc = device_get_softc(bus); - - AML_SDXC_LOCK(sc); - - while (sc->bus_busy) - mtx_sleep(sc, &sc->mtx, PZERO, "sdxc", hz / 5); - sc->bus_busy++; - - AML_SDXC_UNLOCK(sc); - - return (0); -} - -static int -aml8726_sdxc_release_host(device_t bus, device_t child) -{ - struct aml8726_sdxc_softc *sc = device_get_softc(bus); - - AML_SDXC_LOCK(sc); - - sc->bus_busy--; - wakeup(sc); - - AML_SDXC_UNLOCK(sc); - - return (0); -} - -static device_method_t aml8726_sdxc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_sdxc_probe), - DEVMETHOD(device_attach, aml8726_sdxc_attach), - DEVMETHOD(device_detach, aml8726_sdxc_detach), - DEVMETHOD(device_shutdown, aml8726_sdxc_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_read_ivar, aml8726_sdxc_read_ivar), - DEVMETHOD(bus_write_ivar, aml8726_sdxc_write_ivar), - - /* MMC bridge interface */ - DEVMETHOD(mmcbr_update_ios, aml8726_sdxc_update_ios), - DEVMETHOD(mmcbr_request, aml8726_sdxc_request), - DEVMETHOD(mmcbr_get_ro, aml8726_sdxc_get_ro), - DEVMETHOD(mmcbr_acquire_host, aml8726_sdxc_acquire_host), - DEVMETHOD(mmcbr_release_host, aml8726_sdxc_release_host), - - DEVMETHOD_END -}; - -static driver_t aml8726_sdxc_driver = { - "aml8726_sdxc", - aml8726_sdxc_methods, - sizeof(struct aml8726_sdxc_softc), -}; - -static devclass_t aml8726_sdxc_devclass; - -DRIVER_MODULE(aml8726_sdxc, simplebus, aml8726_sdxc_driver, - aml8726_sdxc_devclass, NULL, NULL); -MODULE_DEPEND(aml8726_sdxc, aml8726_gpio, 1, 1, 1); -MMC_DECLARE_BRIDGE(aml8726_sdxc); Index: head/sys/arm/amlogic/aml8726/aml8726_soc.h =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_soc.h +++ head/sys/arm/amlogic/aml8726/aml8726_soc.h @@ -1,58 +0,0 @@ -/*- - * Copyright 2015 John Wehle - * 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 _ARM_AMLOGIC_AML8726_SOC_H -#define _ARM_AMLOGIC_AML8726_SOC_H - -#define AML_SOC_AOBUS_BASE_ADDR 0xc8100000 -#define AML_SOC_CBUS_BASE_ADDR 0xc1100000 - -void aml8726_identify_soc(void); - -/* cbus */ -#define AML_SOC_HW_REV_REG 0x7d4c -#define AML_SOC_HW_REV_UNKNOWN 0xffffffff -#define AML_SOC_HW_REV_M3 0x15 -#define AML_SOC_HW_REV_M6 0x16 -#define AML_SOC_HW_REV_M6TV 0x17 -#define AML_SOC_HW_REV_M6TVL 0x18 -#define AML_SOC_HW_REV_M8 0x19 -#define AML_SOC_HW_REV_M8B 0x1b - -#define AML_SOC_METAL_REV_REG 0x81a8 -#define AML_SOC_METAL_REV_UNKNOWN 0xffffffff -#define AML_SOC_M8_METAL_REV_A 0x11111111 -#define AML_SOC_M8_METAL_REV_M2_A 0x11111112 -#define AML_SOC_M8_METAL_REV_B 0x11111113 -#define AML_SOC_M8_METAL_REV_C 0x11111133 -#define AML_SOC_M8B_METAL_REV_A 0x11111111 - -extern uint32_t aml8726_soc_hw_rev; -extern uint32_t aml8726_soc_metal_rev; - -#endif /* _ARM_AMLOGIC_AML8726_SOC_H */ Index: head/sys/arm/amlogic/aml8726/aml8726_timer.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_timer.c +++ head/sys/arm/amlogic/aml8726/aml8726_timer.c @@ -1,396 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - * - */ - -/* - * Amlogic aml8726 timer driver. - * - * 16 bit Timer A is used for the event timer / hard clock. - * 32 bit Timer E is used for the timecounter / DELAY. - * - * The current implementation doesn't use Timers B-D. Another approach is - * to split the timers between the cores implementing per cpu event timers. - * - * The timers all share the MUX register which requires a mutex to serialize - * access. The mutex is also used to avoid potential problems between the - * interrupt handler and timer_start / timer_stop. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -struct aml8726_timer_softc { - device_t dev; - struct resource * res[2]; - struct mtx mtx; - void * ih_cookie; - struct eventtimer et; - uint32_t first_ticks; - uint32_t period_ticks; - struct timecounter tc; -}; - -static struct resource_spec aml8726_timer_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { SYS_RES_IRQ, 0, RF_ACTIVE }, /* INT_TIMER_A */ - { -1, 0 } -}; - -/* - * devclass_get_device / device_get_softc could be used - * to dynamically locate this, however the timers are a - * required device which can't be unloaded so there's - * no need for the overhead. - */ -static struct aml8726_timer_softc *aml8726_timer_sc = NULL; - -#define AML_TIMER_LOCK(sc) mtx_lock_spin(&(sc)->mtx) -#define AML_TIMER_UNLOCK(sc) mtx_unlock_spin(&(sc)->mtx) -#define AML_TIMER_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "timer", MTX_SPIN) -#define AML_TIMER_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define AML_TIMER_MUX_REG 0 -#define AML_TIMER_INPUT_1us 0 -#define AML_TIMER_INPUT_10us 1 -#define AML_TIMER_INPUT_100us 2 -#define AML_TIMER_INPUT_1ms 3 -#define AML_TIMER_INPUT_MASK 3 -#define AML_TIMER_A_INPUT_MASK 3 -#define AML_TIMER_A_INPUT_SHIFT 0 -#define AML_TIMER_B_INPUT_MASK (3 << 2) -#define AML_TIMER_B_INPUT_SHIFT 2 -#define AML_TIMER_C_INPUT_MASK (3 << 4) -#define AML_TIMER_C_INPUT_SHIFT 4 -#define AML_TIMER_D_INPUT_MASK (3 << 6) -#define AML_TIMER_D_INPUT_SHIFT 6 -#define AML_TIMER_E_INPUT_SYS 0 -#define AML_TIMER_E_INPUT_1us 1 -#define AML_TIMER_E_INPUT_10us 2 -#define AML_TIMER_E_INPUT_100us 3 -#define AML_TIMER_E_INPUT_1ms 4 -#define AML_TIMER_E_INPUT_MASK (7 << 8) -#define AML_TIMER_E_INPUT_SHIFT 8 -#define AML_TIMER_A_PERIODIC (1 << 12) -#define AML_TIMER_B_PERIODIC (1 << 13) -#define AML_TIMER_C_PERIODIC (1 << 14) -#define AML_TIMER_D_PERIODIC (1 << 15) -#define AML_TIMER_A_EN (1 << 16) -#define AML_TIMER_B_EN (1 << 17) -#define AML_TIMER_C_EN (1 << 18) -#define AML_TIMER_D_EN (1 << 19) -#define AML_TIMER_E_EN (1 << 20) -#define AML_TIMER_A_REG 4 -#define AML_TIMER_B_REG 8 -#define AML_TIMER_C_REG 12 -#define AML_TIMER_D_REG 16 -#define AML_TIMER_E_REG 20 - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) - -static unsigned -aml8726_get_timecount(struct timecounter *tc) -{ - struct aml8726_timer_softc *sc = - (struct aml8726_timer_softc *)tc->tc_priv; - - return CSR_READ_4(sc, AML_TIMER_E_REG); -} - -static int -aml8726_hardclock(void *arg) -{ - struct aml8726_timer_softc *sc = (struct aml8726_timer_softc *)arg; - - AML_TIMER_LOCK(sc); - - if (sc->first_ticks != 0 && sc->period_ticks != 0) { - sc->first_ticks = 0; - - CSR_WRITE_4(sc, AML_TIMER_A_REG, sc->period_ticks); - CSR_WRITE_4(sc, AML_TIMER_MUX_REG, - (CSR_READ_4(sc, AML_TIMER_MUX_REG) | - AML_TIMER_A_PERIODIC | AML_TIMER_A_EN)); - } - - AML_TIMER_UNLOCK(sc); - - if (sc->et.et_active) - sc->et.et_event_cb(&sc->et, sc->et.et_arg); - - return (FILTER_HANDLED); -} - -static int -aml8726_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) -{ - struct aml8726_timer_softc *sc = - (struct aml8726_timer_softc *)et->et_priv; - uint32_t first_ticks; - uint32_t period_ticks; - uint32_t periodic; - uint32_t ticks; - - first_ticks = (first * et->et_frequency) / SBT_1S; - period_ticks = (period * et->et_frequency) / SBT_1S; - - if (first_ticks != 0) { - ticks = first_ticks; - periodic = 0; - - } else { - ticks = period_ticks; - periodic = AML_TIMER_A_PERIODIC; - } - - if (ticks == 0) - return (EINVAL); - - AML_TIMER_LOCK(sc); - - sc->first_ticks = first_ticks; - sc->period_ticks = period_ticks; - - CSR_WRITE_4(sc, AML_TIMER_A_REG, ticks); - CSR_WRITE_4(sc, AML_TIMER_MUX_REG, - ((CSR_READ_4(sc, AML_TIMER_MUX_REG) & ~AML_TIMER_A_PERIODIC) | - AML_TIMER_A_EN | periodic)); - - AML_TIMER_UNLOCK(sc); - - return (0); -} - -static int -aml8726_timer_stop(struct eventtimer *et) -{ - struct aml8726_timer_softc *sc = - (struct aml8726_timer_softc *)et->et_priv; - - AML_TIMER_LOCK(sc); - - CSR_WRITE_4(sc, AML_TIMER_MUX_REG, - (CSR_READ_4(sc, AML_TIMER_MUX_REG) & ~AML_TIMER_A_EN)); - - AML_TIMER_UNLOCK(sc); - - return (0); -} - -static int -aml8726_timer_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,meson6-timer")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 timer"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_timer_attach(device_t dev) -{ - struct aml8726_timer_softc *sc = device_get_softc(dev); - - /* There should be exactly one instance. */ - if (aml8726_timer_sc != NULL) - return (ENXIO); - - sc->dev = dev; - - if (bus_alloc_resources(dev, aml8726_timer_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - /* - * Disable the timers, select the input for each timer, - * clear timer E, and then enable timer E. - */ - CSR_WRITE_4(sc, AML_TIMER_MUX_REG, - ((CSR_READ_4(sc, AML_TIMER_MUX_REG) & - ~(AML_TIMER_A_EN | AML_TIMER_A_INPUT_MASK | - AML_TIMER_E_EN | AML_TIMER_E_INPUT_MASK)) | - (AML_TIMER_INPUT_1us << AML_TIMER_A_INPUT_SHIFT) | - (AML_TIMER_E_INPUT_1us << AML_TIMER_E_INPUT_SHIFT))); - - CSR_WRITE_4(sc, AML_TIMER_E_REG, 0); - - CSR_WRITE_4(sc, AML_TIMER_MUX_REG, - (CSR_READ_4(sc, AML_TIMER_MUX_REG) | AML_TIMER_E_EN)); - - /* - * Initialize the mutex prior to installing the interrupt handler - * in case of a spurious interrupt. - */ - AML_TIMER_LOCK_INIT(sc); - - if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, - aml8726_hardclock, NULL, sc, &sc->ih_cookie)) { - device_printf(dev, "could not setup interrupt handler\n"); - bus_release_resources(dev, aml8726_timer_spec, sc->res); - AML_TIMER_LOCK_DESTROY(sc); - return (ENXIO); - } - - aml8726_timer_sc = sc; - - sc->et.et_name = "aml8726 timer A"; - sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; - sc->et.et_frequency = 1000000; - sc->et.et_quality = 1000; - sc->et.et_min_period = (0x00000002LLU * SBT_1S) / sc->et.et_frequency; - sc->et.et_max_period = (0x0000fffeLLU * SBT_1S) / sc->et.et_frequency; - sc->et.et_start = aml8726_timer_start; - sc->et.et_stop = aml8726_timer_stop; - sc->et.et_priv = sc; - - et_register(&sc->et); - - sc->tc.tc_get_timecount = aml8726_get_timecount; - sc->tc.tc_name = "aml8726 timer E"; - sc->tc.tc_frequency = 1000000; - sc->tc.tc_counter_mask = ~0u; - sc->tc.tc_quality = 1000; - sc->tc.tc_priv = sc; - - tc_init(&sc->tc); - - return (0); -} - -static int -aml8726_timer_detach(device_t dev) -{ - - return (EBUSY); -} - -static device_method_t aml8726_timer_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_timer_probe), - DEVMETHOD(device_attach, aml8726_timer_attach), - DEVMETHOD(device_detach, aml8726_timer_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_timer_driver = { - "timer", - aml8726_timer_methods, - sizeof(struct aml8726_timer_softc), -}; - -static devclass_t aml8726_timer_devclass; - -EARLY_DRIVER_MODULE(timer, simplebus, aml8726_timer_driver, - aml8726_timer_devclass, 0, 0, BUS_PASS_TIMER); - -void -DELAY(int usec) -{ - uint32_t counter; - uint32_t delta, now, previous, remaining; - - /* Timer has not yet been initialized */ - if (aml8726_timer_sc == NULL) { - for (; usec > 0; usec--) - for (counter = 200; counter > 0; counter--) { - /* Prevent gcc from optimizing out the loop */ - cpufunc_nullop(); - } - return; - } - TSENTER(); - - /* - * Some of the other timers in the source tree do this calculation as: - * - * usec * ((sc->tc.tc_frequency / 1000000) + 1) - * - * which gives a fairly pessimistic result when tc_frequency is an exact - * multiple of 1000000. Given the data type and typical values for - * tc_frequency adding 999999 shouldn't overflow. - */ - remaining = usec * ((aml8726_timer_sc->tc.tc_frequency + 999999) / - 1000000); - - /* - * We add one since the first iteration may catch the counter just - * as it is changing. - */ - remaining += 1; - - previous = aml8726_get_timecount(&aml8726_timer_sc->tc); - - for ( ; ; ) { - now = aml8726_get_timecount(&aml8726_timer_sc->tc); - - /* - * If the timer has rolled over, then we have the case: - * - * if (previous > now) { - * delta = (0 - previous) + now - * } - * - * which is really no different then the normal case. - * Both cases are simply: - * - * delta = now - previous. - */ - delta = now - previous; - - if (delta >= remaining) - break; - - previous = now; - remaining -= delta; - } - TSEXIT(); -} Index: head/sys/arm/amlogic/aml8726/aml8726_uart.h =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_uart.h +++ head/sys/arm/amlogic/aml8726/aml8726_uart.h @@ -1,107 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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 _ARM_AMLOGIC_AML8726_UART_H -#define _ARM_AMLOGIC_AML8726_UART_H - -#define AML_UART_WFIFO_REG 0 - -#define AML_UART_RFIFO_REG 4 - -#define AML_UART_CONTROL_REG 8 -#define AML_UART_CONTROL_TX_INT_EN (1 << 28) -#define AML_UART_CONTROL_RX_INT_EN (1 << 27) -#define AML_UART_CONTROL_CLR_ERR (1 << 24) -#define AML_UART_CONTROL_RX_RST (1 << 23) -#define AML_UART_CONTROL_TX_RST (1 << 22) -#define AML_UART_CONTROL_DB_MASK (3 << 20) -#define AML_UART_CONTROL_8_DB (0 << 20) -#define AML_UART_CONTROL_7_DB (1 << 20) -#define AML_UART_CONTROL_6_DB (2 << 20) -#define AML_UART_CONTROL_5_DB (3 << 20) -#define AML_UART_CONTROL_P_MASK (3 << 18) -#define AML_UART_CONTROL_P_EN (1 << 19) -#define AML_UART_CONTROL_P_EVEN (0 << 18) -#define AML_UART_CONTROL_P_ODD (1 << 18) -#define AML_UART_CONTROL_SB_MASK (3 << 16) -#define AML_UART_CONTROL_1_SB (0 << 16) -#define AML_UART_CONTROL_2_SB (1 << 16) -#define AML_UART_CONTROL_TWO_WIRE_EN (1 << 15) -#define AML_UART_CONTROL_RX_EN (1 << 13) -#define AML_UART_CONTROL_TX_EN (1 << 12) -#define AML_UART_CONTROL_BAUD_MASK 0xfff -#define AML_UART_CONTROL_BAUD_WIDTH 12 - -#define AML_UART_STATUS_REG 12 -#define AML_UART_STATUS_RECV_BUSY (1 << 26) -#define AML_UART_STATUS_XMIT_BUSY (1 << 25) -#define AML_UART_STATUS_RX_FIFO_OVERFLOW (1 << 24) -#define AML_UART_STATUS_TX_FIFO_EMPTY (1 << 22) -#define AML_UART_STATUS_TX_FIFO_FULL (1 << 21) -#define AML_UART_STATUS_RX_FIFO_EMPTY (1 << 20) -#define AML_UART_STATUS_RX_FIFO_FULL (1 << 19) -#define AML_UART_STATUS_TX_FIFO_WRITE_ERR (1 << 18) -#define AML_UART_STATUS_FRAME_ERR (1 << 17) -#define AML_UART_STATUS_PARITY_ERR (1 << 16) -#define AML_UART_STATUS_TX_FIFO_CNT_MASK (0x7f << 8) -#define AML_UART_STATUS_TX_FIFO_CNT_SHIFT 8 -#define AML_UART_STATUS_RX_FIFO_CNT_MASK (0x7f << 0) -#define AML_UART_STATUS_RX_FIFO_CNT_SHIFT 0 - -#define AML_UART_MISC_REG 16 -#define AML_UART_MISC_OLD_RX_BAUD (1 << 30) -#define AML_UART_MISC_BAUD_EXT_MASK (0xf << 20) -#define AML_UART_MISC_BAUD_EXT_SHIFT 20 - -/* - * The documentation appears to be incorrect as the - * IRQ is actually generated when TX FIFO count is - * * equal to * or less than the selected threshold. - */ -#define AML_UART_MISC_XMIT_IRQ_CNT_MASK (0xff << 8) -#define AML_UART_MISC_XMIT_IRQ_CNT_SHIFT 8 - -/* - * The documentation appears to be incorrect as the - * IRQ is actually generated when RX FIFO count is - * * equal to * or greater than the selected threshold. - */ -#define AML_UART_MISC_RECV_IRQ_CNT_MASK 0xff -#define AML_UART_MISC_RECV_IRQ_CNT_SHIFT 0 - -/* - * The new baud rate register is available on the - * aml8726-m6 and later. - */ -#define AML_UART_NEW_BAUD_REG 20 -#define AML_UART_NEW_BAUD_USE_XTAL_CLK (1 << 24) -#define AML_UART_NEW_BAUD_RATE_EN (1 << 23) -#define AML_UART_NEW_BAUD_RATE_MASK (0x7fffff << 0) -#define AML_UART_NEW_BAUD_RATE_SHIFT 0 - -#endif /* _ARM_AMLOGIC_AML8726_UART_H */ Index: head/sys/arm/amlogic/aml8726/aml8726_uart_console.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_uart_console.c +++ head/sys/arm/amlogic/aml8726/aml8726_uart_console.c @@ -1,180 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 UART console driver. - * - * This is only necessary to use when debugging early boot code. - * The standard uart driver is available for use later in the boot. - * - * It's assumed the SoC uart is mapped into AML_UART_KVM_BASE meaning - * when using EARLY_PRINTF you'll need to define SOCDEV_VA to be - * 0xd8100000 and SOCDEV_PA to be 0xc8100000 in your config file. - */ - -#include "opt_global.h" - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#define AML_UART_KVM_BASE (aml8726_aobus_kva_base + 0x130 * 4) - -static uint32_t -ub_getreg(uint32_t off) -{ - - return *((volatile uint32_t *)(AML_UART_KVM_BASE + off)); -} - -static void -ub_setreg(uint32_t off, uint32_t val) -{ - - *((volatile uint32_t *)(AML_UART_KVM_BASE + off)) = val; -} - -static void -uart_cnprobe(struct consdev *cp) -{ - - sprintf(cp->cn_name, "uart"); - cp->cn_pri = CN_REMOTE; -} - -static void -uart_cngrab(struct consdev *cp) -{ -} - -static void -uart_cnungrab(struct consdev *cp) -{ -} - -static void -uart_cninit(struct consdev *cp) -{ - uint32_t cr; - uint32_t mr; - -#ifdef EARLY_PRINTF - if (early_putc != NULL) { - printf("Early printf yielding control to the real console.\n"); - early_putc = NULL; - } - - /* - * Give pending characters a chance to drain. - */ - DELAY(4000); -#endif - - cr = ub_getreg(AML_UART_CONTROL_REG); - /* Disable all interrupt sources. */ - cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); - /* Reset the transmitter and receiver. */ - cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); - /* Use two wire mode. */ - cr |= AML_UART_CONTROL_TWO_WIRE_EN; - /* Enable the transmitter and receiver. */ - cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN); - ub_setreg(AML_UART_CONTROL_REG, cr); - - /* Clear RX FIFO level for generating interrupts. */ - mr = ub_getreg(AML_UART_MISC_REG); - mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; - ub_setreg(AML_UART_MISC_REG, mr); - - /* Ensure the reset bits are clear. */ - cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); - ub_setreg(AML_UART_CONTROL_REG, cr); -} - -static void -uart_cnterm(struct consdev * cp) -{ -} - -static void -uart_cnputc(struct consdev *cp, int c) -{ - - while ((ub_getreg(AML_UART_STATUS_REG) & - AML_UART_STATUS_TX_FIFO_FULL) != 0) - cpu_spinwait(); - - ub_setreg(AML_UART_WFIFO_REG, c); -} - -static int -uart_cngetc(struct consdev * cp) -{ - int c; - - if ((ub_getreg(AML_UART_STATUS_REG) & - AML_UART_STATUS_RX_FIFO_EMPTY) != 0) - return (-1); - - c = ub_getreg(AML_UART_RFIFO_REG) & 0xff; - - return (c); -} - -CONSOLE_DRIVER(uart); - -#ifdef EARLY_PRINTF - -#if !(defined(SOCDEV_PA) && defined(SOCDEV_VA)) -#error SOCDEV_PA and SOCDEV_VA must be defined. -#endif - -static void -eputc(int c) -{ - - if (c == '\n') - eputc('\r'); - - uart_cnputc(NULL, c); -} - -early_putc_t *early_putc = eputc; -#endif Index: head/sys/arm/amlogic/aml8726/aml8726_usb_phy-m3.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_usb_phy-m3.c +++ head/sys/arm/amlogic/aml8726/aml8726_usb_phy-m3.c @@ -1,428 +0,0 @@ -/*- - * Copyright 2014-2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726-m3 USB physical layer driver. - * - * Both USB physical interfaces share the same configuration register. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include "gpio_if.h" - -struct aml8726_usb_phy_gpio { - device_t dev; - uint32_t pin; - uint32_t pol; -}; - -struct aml8726_usb_phy_softc { - device_t dev; - struct resource *res[1]; - uint32_t npwr_en; - struct aml8726_usb_phy_gpio *pwr_en; -}; - -static struct resource_spec aml8726_usb_phy_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, 0 } -}; - -#define AML_USB_PHY_CFG_REG 0 -#define AML_USB_PHY_CFG_A_CLK_DETECTED (1U << 31) -#define AML_USB_PHY_CFG_CLK_DIV_MASK (0x7f << 24) -#define AML_USB_PHY_CFG_CLK_DIV_SHIFT 24 -#define AML_USB_PHY_CFG_B_CLK_DETECTED (1 << 22) -#define AML_USB_PHY_CFG_A_PLL_RST (1 << 19) -#define AML_USB_PHY_CFG_A_PHYS_RST (1 << 18) -#define AML_USB_PHY_CFG_A_RST (1 << 17) -#define AML_USB_PHY_CFG_B_PLL_RST (1 << 13) -#define AML_USB_PHY_CFG_B_PHYS_RST (1 << 12) -#define AML_USB_PHY_CFG_B_RST (1 << 11) -#define AML_USB_PHY_CFG_CLK_EN (1 << 8) -#define AML_USB_PHY_CFG_CLK_SEL_MASK (7 << 5) -#define AML_USB_PHY_CFG_CLK_SEL_XTAL (0 << 5) -#define AML_USB_PHY_CFG_CLK_SEL_XTAL_DIV2 (1 << 5) -#define AML_USB_PHY_CFG_B_POR (1 << 1) -#define AML_USB_PHY_CFG_A_POR (1 << 0) - -#define AML_USB_PHY_CFG_CLK_DETECTED \ - (AML_USB_PHY_CFG_A_CLK_DETECTED | AML_USB_PHY_CFG_B_CLK_DETECTED) - -#define AML_USB_PHY_MISC_A_REG 12 -#define AML_USB_PHY_MISC_B_REG 16 -#define AML_USB_PHY_MISC_ID_OVERIDE_EN (1 << 23) -#define AML_USB_PHY_MISC_ID_OVERIDE_DEVICE (1 << 22) -#define AML_USB_PHY_MISC_ID_OVERIDE_HOST (0 << 22) - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) -#define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ - (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -#define PIN_ON_FLAG(pol) ((pol) == 0 ? \ - GPIO_PIN_LOW : GPIO_PIN_HIGH) -#define PIN_OFF_FLAG(pol) ((pol) == 0 ? \ - GPIO_PIN_HIGH : GPIO_PIN_LOW) - -static int -aml8726_usb_phy_mode(const char *dwcotg_path, uint32_t *mode) -{ - char *usb_mode; - phandle_t node; - ssize_t len; - - if ((node = OF_finddevice(dwcotg_path)) == -1) - return (ENXIO); - - if (fdt_is_compatible_strict(node, "synopsys,designware-hs-otg2") == 0) - return (ENXIO); - - *mode = 0; - - len = OF_getprop_alloc(node, "dr_mode", - (void **)&usb_mode); - - if (len <= 0) - return (0); - - if (strcasecmp(usb_mode, "host") == 0) { - *mode = AML_USB_PHY_MISC_ID_OVERIDE_EN | - AML_USB_PHY_MISC_ID_OVERIDE_HOST; - } else if (strcasecmp(usb_mode, "peripheral") == 0) { - *mode = AML_USB_PHY_MISC_ID_OVERIDE_EN | - AML_USB_PHY_MISC_ID_OVERIDE_DEVICE; - } - - OF_prop_free(usb_mode); - - return (0); -} - -static int -aml8726_usb_phy_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-m3-usb-phy")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726-m3 USB PHY"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_usb_phy_attach(device_t dev) -{ - struct aml8726_usb_phy_softc *sc = device_get_softc(dev); - int err; - int npwr_en; - pcell_t *prop; - phandle_t node; - ssize_t len; - uint32_t div; - uint32_t i; - uint32_t mode_a; - uint32_t mode_b; - uint32_t value; - - sc->dev = dev; - - if (aml8726_usb_phy_mode("/soc/usb@c9040000", &mode_a) != 0) { - device_printf(dev, "missing usb@c9040000 node in FDT\n"); - return (ENXIO); - } - - if (aml8726_usb_phy_mode("/soc/usb@c90c0000", &mode_b) != 0) { - device_printf(dev, "missing usb@c90c0000 node in FDT\n"); - return (ENXIO); - } - - if (bus_alloc_resources(dev, aml8726_usb_phy_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - node = ofw_bus_get_node(dev); - - err = 0; - - len = OF_getencprop_alloc_multi(node, "usb-pwr-en", - 3 * sizeof(pcell_t), (void **)&prop); - npwr_en = (len > 0) ? len : 0; - - sc->npwr_en = 0; - sc->pwr_en = (struct aml8726_usb_phy_gpio *) - malloc(npwr_en * sizeof (*sc->pwr_en), M_DEVBUF, M_WAITOK); - - for (i = 0; i < npwr_en; i++) { - sc->pwr_en[i].dev = OF_device_from_xref(prop[i * 3]); - sc->pwr_en[i].pin = prop[i * 3 + 1]; - sc->pwr_en[i].pol = prop[i * 3 + 2]; - - if (sc->pwr_en[i].dev == NULL) { - err = 1; - break; - } - } - - OF_prop_free(prop); - - if (err) { - device_printf(dev, "unable to parse gpio\n"); - goto fail; - } - - /* Turn on power by setting pin and then enabling output driver. */ - for (i = 0; i < npwr_en; i++) { - if (GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, - PIN_ON_FLAG(sc->pwr_en[i].pol)) != 0 || - GPIO_PIN_SETFLAGS(sc->pwr_en[i].dev, sc->pwr_en[i].pin, - GPIO_PIN_OUTPUT) != 0) { - device_printf(dev, - "could not use gpio to control power\n"); - goto fail; - } - - sc->npwr_en++; - } - - /* - * Configure the clock source and divider. - */ - - div = 2; - - value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG); - - value &= ~(AML_USB_PHY_CFG_CLK_DIV_MASK | AML_USB_PHY_CFG_CLK_SEL_MASK); - - value &= ~(AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST); - value &= ~(AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST); - value &= ~(AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST); - value &= ~(AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR); - - value |= AML_USB_PHY_CFG_CLK_SEL_XTAL; - value |= ((div - 1) << AML_USB_PHY_CFG_CLK_DIV_SHIFT) & - AML_USB_PHY_CFG_CLK_DIV_MASK; - value |= AML_USB_PHY_CFG_CLK_EN; - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - /* - * Issue the reset sequence. - */ - - value |= (AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST); - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - DELAY(200); - - value &= ~(AML_USB_PHY_CFG_A_RST | AML_USB_PHY_CFG_B_RST); - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - DELAY(200); - - value |= (AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST); - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - DELAY(200); - - value &= ~(AML_USB_PHY_CFG_A_PLL_RST | AML_USB_PHY_CFG_B_PLL_RST); - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - DELAY(200); - - value |= (AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST); - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - DELAY(200); - - value &= ~(AML_USB_PHY_CFG_A_PHYS_RST | AML_USB_PHY_CFG_B_PHYS_RST); - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - DELAY(200); - - value |= (AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR); - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - DELAY(200); - - /* - * Enable by clearing the power on reset. - */ - - value &= ~(AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR); - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - DELAY(200); - - /* - * Check if the clock was detected. - */ - value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG); - if ((value & AML_USB_PHY_CFG_CLK_DETECTED) != - AML_USB_PHY_CFG_CLK_DETECTED) - device_printf(dev, "PHY Clock not detected\n"); - - /* - * Configure the mode for each port. - */ - - value = CSR_READ_4(sc, AML_USB_PHY_MISC_A_REG); - - value &= ~(AML_USB_PHY_MISC_ID_OVERIDE_EN | - AML_USB_PHY_MISC_ID_OVERIDE_DEVICE | - AML_USB_PHY_MISC_ID_OVERIDE_HOST); - value |= mode_a; - - CSR_WRITE_4(sc, AML_USB_PHY_MISC_A_REG, value); - - value = CSR_READ_4(sc, AML_USB_PHY_MISC_B_REG); - - value &= ~(AML_USB_PHY_MISC_ID_OVERIDE_EN | - AML_USB_PHY_MISC_ID_OVERIDE_DEVICE | - AML_USB_PHY_MISC_ID_OVERIDE_HOST); - value |= mode_b; - - CSR_WRITE_4(sc, AML_USB_PHY_MISC_B_REG, value); - - CSR_BARRIER(sc, AML_USB_PHY_MISC_B_REG); - - return (0); - -fail: - /* In the event of problems attempt to turn things back off. */ - i = sc->npwr_en; - while (i-- != 0) { - GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, - PIN_OFF_FLAG(sc->pwr_en[i].pol)); - } - - free (sc->pwr_en, M_DEVBUF); - sc->pwr_en = NULL; - - bus_release_resources(dev, aml8726_usb_phy_spec, sc->res); - - return (ENXIO); -} - -static int -aml8726_usb_phy_detach(device_t dev) -{ - struct aml8726_usb_phy_softc *sc = device_get_softc(dev); - uint32_t i; - uint32_t value; - - /* - * Disable by issuing a power on reset. - */ - - value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG); - - value |= (AML_USB_PHY_CFG_A_POR | AML_USB_PHY_CFG_B_POR); - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - /* Turn off power */ - i = sc->npwr_en; - while (i-- != 0) { - (void)GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, - PIN_OFF_FLAG(sc->pwr_en[i].pol)); - } - free (sc->pwr_en, M_DEVBUF); - sc->pwr_en = NULL; - - bus_release_resources(dev, aml8726_usb_phy_spec, sc->res); - - return (0); -} - -static device_method_t aml8726_usb_phy_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_usb_phy_probe), - DEVMETHOD(device_attach, aml8726_usb_phy_attach), - DEVMETHOD(device_detach, aml8726_usb_phy_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_usb_phy_driver = { - "usbphy", - aml8726_usb_phy_methods, - sizeof(struct aml8726_usb_phy_softc), -}; - -static devclass_t aml8726_usb_phy_devclass; - -DRIVER_MODULE(aml8726_m3usbphy, simplebus, aml8726_usb_phy_driver, - aml8726_usb_phy_devclass, 0, 0); -MODULE_DEPEND(aml8726_m3usbphy, aml8726_gpio, 1, 1, 1); Index: head/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c +++ head/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c @@ -1,418 +0,0 @@ -/*- - * Copyright 2014-2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726-m6 (and later) USB physical layer driver. - * - * Each USB physical interface has a dedicated register block. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include - -#include "gpio_if.h" - -struct aml8726_usb_phy_gpio { - device_t dev; - uint32_t pin; - uint32_t pol; -}; - -struct aml8726_usb_phy_softc { - device_t dev; - struct resource *res[1]; - uint32_t npwr_en; - struct aml8726_usb_phy_gpio *pwr_en; - boolean_t force_aca; - struct aml8726_usb_phy_gpio hub_rst; -}; - -static struct resource_spec aml8726_usb_phy_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, 0 } -}; - -#define AML_USB_PHY_CFG_REG 0 -#define AML_USB_PHY_CFG_CLK_SEL_32K_ALT (1 << 15) -#define AML_USB_PHY_CFG_CLK_DIV_MASK (0x7f << 4) -#define AML_USB_PHY_CFG_CLK_DIV_SHIFT 4 -#define AML_USB_PHY_CFG_CLK_SEL_MASK (7 << 1) -#define AML_USB_PHY_CFG_CLK_SEL_XTAL (0 << 1) -#define AML_USB_PHY_CFG_CLK_SEL_XTAL_DIV2 (1 << 1) -#define AML_USB_PHY_CFG_CLK_EN (1 << 0) - -#define AML_USB_PHY_CTRL_REG 4 -#define AML_USB_PHY_CTRL_FSEL_MASK (7 << 22) -#define AML_USB_PHY_CTRL_FSEL_12M (2 << 22) -#define AML_USB_PHY_CTRL_FSEL_24M (5 << 22) -#define AML_USB_PHY_CTRL_POR (1 << 15) -#define AML_USB_PHY_CTRL_CLK_DETECTED (1 << 8) - -#define AML_USB_PHY_ADP_BC_REG 12 -#define AML_USB_PHY_ADP_BC_ACA_FLOATING (1 << 26) -#define AML_USB_PHY_ADP_BC_ACA_EN (1 << 16) - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) -#define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ - (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -#define PIN_ON_FLAG(pol) ((pol) == 0 ? \ - GPIO_PIN_LOW : GPIO_PIN_HIGH) -#define PIN_OFF_FLAG(pol) ((pol) == 0 ? \ - GPIO_PIN_HIGH : GPIO_PIN_LOW) - -static int -aml8726_usb_phy_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-m6-usb-phy") && - !ofw_bus_is_compatible(dev, "amlogic,aml8726-m8-usb-phy")) - return (ENXIO); - - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M8: - case AML_SOC_HW_REV_M8B: - device_set_desc(dev, "Amlogic aml8726-m8 USB PHY"); - break; - default: - device_set_desc(dev, "Amlogic aml8726-m6 USB PHY"); - break; - } - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_usb_phy_attach(device_t dev) -{ - struct aml8726_usb_phy_softc *sc = device_get_softc(dev); - char *force_aca; - int err; - int npwr_en; - pcell_t *prop; - phandle_t node; - ssize_t len; - uint32_t div; - uint32_t i; - uint32_t value; - - sc->dev = dev; - - if (bus_alloc_resources(dev, aml8726_usb_phy_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - node = ofw_bus_get_node(dev); - - len = OF_getprop_alloc(node, "force-aca", - (void **)&force_aca); - - sc->force_aca = FALSE; - - if (len > 0) { - if (strncmp(force_aca, "true", len) == 0) - sc->force_aca = TRUE; - } - - OF_prop_free(force_aca); - - err = 0; - - len = OF_getencprop_alloc_multi(node, "usb-pwr-en", - 3 * sizeof(pcell_t), (void **)&prop); - npwr_en = (len > 0) ? len : 0; - - sc->npwr_en = 0; - sc->pwr_en = (struct aml8726_usb_phy_gpio *) - malloc(npwr_en * sizeof (*sc->pwr_en), M_DEVBUF, M_WAITOK); - - for (i = 0; i < npwr_en; i++) { - sc->pwr_en[i].dev = OF_device_from_xref(prop[i * 3]); - sc->pwr_en[i].pin = prop[i * 3 + 1]; - sc->pwr_en[i].pol = prop[i * 3 + 2]; - - if (sc->pwr_en[i].dev == NULL) { - err = 1; - break; - } - } - - OF_prop_free(prop); - - len = OF_getencprop_alloc_multi(node, "usb-hub-rst", - 3 * sizeof(pcell_t), (void **)&prop); - if (len > 0) { - sc->hub_rst.dev = OF_device_from_xref(prop[0]); - sc->hub_rst.pin = prop[1]; - sc->hub_rst.pol = prop[2]; - - if (len > 1 || sc->hub_rst.dev == NULL) - err = 1; - } - - OF_prop_free(prop); - - if (err) { - device_printf(dev, "unable to parse gpio\n"); - goto fail; - } - - /* Turn on power by setting pin and then enabling output driver. */ - for (i = 0; i < npwr_en; i++) { - if (GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, - PIN_ON_FLAG(sc->pwr_en[i].pol)) != 0 || - GPIO_PIN_SETFLAGS(sc->pwr_en[i].dev, sc->pwr_en[i].pin, - GPIO_PIN_OUTPUT) != 0) { - device_printf(dev, - "could not use gpio to control power\n"); - goto fail; - } - - sc->npwr_en++; - } - - /* - * Configure the clock source and divider. - */ - - value = CSR_READ_4(sc, AML_USB_PHY_CFG_REG); - - value &= ~(AML_USB_PHY_CFG_CLK_SEL_32K_ALT | - AML_USB_PHY_CFG_CLK_DIV_MASK | - AML_USB_PHY_CFG_CLK_SEL_MASK | - AML_USB_PHY_CFG_CLK_EN); - - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M8: - case AML_SOC_HW_REV_M8B: - value |= AML_USB_PHY_CFG_CLK_SEL_32K_ALT; - break; - default: - div = 2; - value |= AML_USB_PHY_CFG_CLK_SEL_XTAL; - value |= ((div - 1) << AML_USB_PHY_CFG_CLK_DIV_SHIFT) & - AML_USB_PHY_CFG_CLK_DIV_MASK; - value |= AML_USB_PHY_CFG_CLK_EN; - break; - } - - CSR_WRITE_4(sc, AML_USB_PHY_CFG_REG, value); - - CSR_BARRIER(sc, AML_USB_PHY_CFG_REG); - - /* - * Configure the clock frequency and issue a power on reset. - */ - - value = CSR_READ_4(sc, AML_USB_PHY_CTRL_REG); - - value &= ~AML_USB_PHY_CTRL_FSEL_MASK; - - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M8: - case AML_SOC_HW_REV_M8B: - value |= AML_USB_PHY_CTRL_FSEL_24M; - break; - default: - value |= AML_USB_PHY_CTRL_FSEL_12M; - break; - } - - value |= AML_USB_PHY_CTRL_POR; - - CSR_WRITE_4(sc, AML_USB_PHY_CTRL_REG, value); - - CSR_BARRIER(sc, AML_USB_PHY_CTRL_REG); - - DELAY(500); - - /* - * Enable by clearing the power on reset. - */ - - value &= ~AML_USB_PHY_CTRL_POR; - - CSR_WRITE_4(sc, AML_USB_PHY_CTRL_REG, value); - - CSR_BARRIER(sc, AML_USB_PHY_CTRL_REG); - - DELAY(1000); - - /* - * Check if the clock was detected. - */ - value = CSR_READ_4(sc, AML_USB_PHY_CTRL_REG); - if ((value & AML_USB_PHY_CTRL_CLK_DETECTED) == 0) - device_printf(dev, "PHY Clock not detected\n"); - - /* - * If necessary enabled Accessory Charger Adaptor detection - * so that the port knows what mode to operate in. - */ - if (sc->force_aca) { - value = CSR_READ_4(sc, AML_USB_PHY_ADP_BC_REG); - - value |= AML_USB_PHY_ADP_BC_ACA_EN; - - CSR_WRITE_4(sc, AML_USB_PHY_ADP_BC_REG, value); - - CSR_BARRIER(sc, AML_USB_PHY_ADP_BC_REG); - - DELAY(50); - - value = CSR_READ_4(sc, AML_USB_PHY_ADP_BC_REG); - - if ((value & AML_USB_PHY_ADP_BC_ACA_FLOATING) != 0) { - device_printf(dev, - "force-aca requires newer silicon\n"); - goto fail; - } - } - - /* - * Reset the hub. - */ - if (sc->hub_rst.dev != NULL) { - err = 0; - - if (GPIO_PIN_SET(sc->hub_rst.dev, sc->hub_rst.pin, - PIN_ON_FLAG(sc->hub_rst.pol)) != 0 || - GPIO_PIN_SETFLAGS(sc->hub_rst.dev, sc->hub_rst.pin, - GPIO_PIN_OUTPUT) != 0) - err = 1; - - DELAY(30); - - if (GPIO_PIN_SET(sc->hub_rst.dev, sc->hub_rst.pin, - PIN_OFF_FLAG(sc->hub_rst.pol)) != 0) - err = 1; - - DELAY(60000); - - if (err) { - device_printf(dev, - "could not use gpio to reset hub\n"); - goto fail; - } - } - - return (0); - -fail: - /* In the event of problems attempt to turn things back off. */ - i = sc->npwr_en; - while (i-- != 0) { - GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, - PIN_OFF_FLAG(sc->pwr_en[i].pol)); - } - - free (sc->pwr_en, M_DEVBUF); - sc->pwr_en = NULL; - - bus_release_resources(dev, aml8726_usb_phy_spec, sc->res); - - return (ENXIO); -} - -static int -aml8726_usb_phy_detach(device_t dev) -{ - struct aml8726_usb_phy_softc *sc = device_get_softc(dev); - uint32_t i; - uint32_t value; - - /* - * Disable by issuing a power on reset. - */ - - value = CSR_READ_4(sc, AML_USB_PHY_CTRL_REG); - - value |= AML_USB_PHY_CTRL_POR; - - CSR_WRITE_4(sc, AML_USB_PHY_CTRL_REG, value); - - CSR_BARRIER(sc, AML_USB_PHY_CTRL_REG); - - /* Turn off power */ - i = sc->npwr_en; - while (i-- != 0) { - GPIO_PIN_SET(sc->pwr_en[i].dev, sc->pwr_en[i].pin, - PIN_OFF_FLAG(sc->pwr_en[i].pol)); - } - free (sc->pwr_en, M_DEVBUF); - sc->pwr_en = NULL; - - bus_release_resources(dev, aml8726_usb_phy_spec, sc->res); - - return (0); -} - -static device_method_t aml8726_usb_phy_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_usb_phy_probe), - DEVMETHOD(device_attach, aml8726_usb_phy_attach), - DEVMETHOD(device_detach, aml8726_usb_phy_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_usb_phy_driver = { - "usbphy", - aml8726_usb_phy_methods, - sizeof(struct aml8726_usb_phy_softc), -}; - -static devclass_t aml8726_usb_phy_devclass; - -DRIVER_MODULE(aml8726_m6usbphy, simplebus, aml8726_usb_phy_driver, - aml8726_usb_phy_devclass, 0, 0); -MODULE_DEPEND(aml8726_m6usbphy, aml8726_gpio, 1, 1, 1); Index: head/sys/arm/amlogic/aml8726/aml8726_wdt.c =================================================================== --- head/sys/arm/amlogic/aml8726/aml8726_wdt.c +++ head/sys/arm/amlogic/aml8726/aml8726_wdt.c @@ -1,305 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - * - */ - -/* - * Amlogic aml8726 watchdog driver. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include - -struct aml8726_wdt_softc { - device_t dev; - struct resource * res[2]; - struct mtx mtx; - void * ih_cookie; -}; - -static struct resource_spec aml8726_wdt_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { SYS_RES_IRQ, 0, RF_ACTIVE }, - { -1, 0 } -}; - -static struct { - uint32_t ctrl_cpu_mask; - uint32_t ctrl_en; - uint32_t term_cnt_mask; - uint32_t reset_cnt_mask; -} aml8726_wdt_soc_params; - -/* - * devclass_get_device / device_get_softc could be used - * to dynamically locate this, however the wdt is a - * required device which can't be unloaded so there's - * no need for the overhead. - */ -static struct aml8726_wdt_softc *aml8726_wdt_sc = NULL; - -#define AML_WDT_LOCK(sc) mtx_lock_spin(&(sc)->mtx) -#define AML_WDT_UNLOCK(sc) mtx_unlock_spin(&(sc)->mtx) -#define AML_WDT_LOCK_INIT(sc) \ - mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ - "wdt", MTX_SPIN) -#define AML_WDT_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx); - -#define AML_WDT_CTRL_REG 0 -#define AML_WDT_CTRL_CPU_WDRESET_MASK aml8726_wdt_soc_params.ctrl_cpu_mask -#define AML_WDT_CTRL_CPU_WDRESET_SHIFT 24 -#define AML_WDT_CTRL_IRQ_EN (1 << 23) -#define AML_WDT_CTRL_EN aml8726_wdt_soc_params.ctrl_en -#define AML_WDT_CTRL_TERMINAL_CNT_MASK aml8726_wdt_soc_params.term_cnt_mask -#define AML_WDT_CTRL_TERMINAL_CNT_SHIFT 0 -#define AML_WDT_RESET_REG 4 -#define AML_WDT_RESET_CNT_MASK aml8726_wdt_soc_params.reset_cnt_mask -#define AML_WDT_RESET_CNT_SHIFT 0 - -#define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val)) -#define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg) -#define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \ - (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) - -static void -aml8726_wdt_watchdog(void *private, u_int cmd, int *error) -{ - struct aml8726_wdt_softc *sc = (struct aml8726_wdt_softc *)private; - uint32_t wcr; - uint64_t tens_of_usec; - - AML_WDT_LOCK(sc); - - tens_of_usec = (((uint64_t)1 << (cmd & WD_INTERVAL)) + 9999) / 10000; - - if (cmd != 0 && tens_of_usec <= (AML_WDT_CTRL_TERMINAL_CNT_MASK >> - AML_WDT_CTRL_TERMINAL_CNT_SHIFT)) { - wcr = AML_WDT_CTRL_CPU_WDRESET_MASK | - AML_WDT_CTRL_EN | ((uint32_t)tens_of_usec << - AML_WDT_CTRL_TERMINAL_CNT_SHIFT); - - CSR_WRITE_4(sc, AML_WDT_RESET_REG, 0); - CSR_WRITE_4(sc, AML_WDT_CTRL_REG, wcr); - - *error = 0; - } else - CSR_WRITE_4(sc, AML_WDT_CTRL_REG, - (CSR_READ_4(sc, AML_WDT_CTRL_REG) & - ~(AML_WDT_CTRL_IRQ_EN | AML_WDT_CTRL_EN))); - - AML_WDT_UNLOCK(sc); -} - -static int -aml8726_wdt_intr(void *arg) -{ - struct aml8726_wdt_softc *sc = (struct aml8726_wdt_softc *)arg; - - /* - * Normally a timeout causes a hardware reset, however - * the watchdog timer can be configured to cause an - * interrupt instead by setting AML_WDT_CTRL_IRQ_EN - * and clearing AML_WDT_CTRL_CPU_WDRESET_MASK. - */ - - AML_WDT_LOCK(sc); - - CSR_WRITE_4(sc, AML_WDT_CTRL_REG, - (CSR_READ_4(sc, AML_WDT_CTRL_REG) & ~(AML_WDT_CTRL_IRQ_EN | - AML_WDT_CTRL_EN))); - - CSR_BARRIER(sc, AML_WDT_CTRL_REG); - - AML_WDT_UNLOCK(sc); - - device_printf(sc->dev, "timeout expired\n"); - - return (FILTER_HANDLED); -} - -static int -aml8726_wdt_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "amlogic,meson6-wdt")) - return (ENXIO); - - device_set_desc(dev, "Amlogic aml8726 WDT"); - - return (BUS_PROBE_DEFAULT); -} - -static int -aml8726_wdt_attach(device_t dev) -{ - struct aml8726_wdt_softc *sc = device_get_softc(dev); - - /* There should be exactly one instance. */ - if (aml8726_wdt_sc != NULL) - return (ENXIO); - - sc->dev = dev; - - if (bus_alloc_resources(dev, aml8726_wdt_spec, sc->res)) { - device_printf(dev, "can not allocate resources for device\n"); - return (ENXIO); - } - - /* - * Certain bitfields are dependent on the hardware revision. - */ - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M8: - aml8726_wdt_soc_params.ctrl_cpu_mask = 0xf << - AML_WDT_CTRL_CPU_WDRESET_SHIFT; - switch (aml8726_soc_metal_rev) { - case AML_SOC_M8_METAL_REV_M2_A: - aml8726_wdt_soc_params.ctrl_en = 1 << 19; - aml8726_wdt_soc_params.term_cnt_mask = 0x07ffff << - AML_WDT_CTRL_TERMINAL_CNT_SHIFT; - aml8726_wdt_soc_params.reset_cnt_mask = 0x07ffff << - AML_WDT_RESET_CNT_SHIFT; - break; - default: - aml8726_wdt_soc_params.ctrl_en = 1 << 22; - aml8726_wdt_soc_params.term_cnt_mask = 0x3fffff << - AML_WDT_CTRL_TERMINAL_CNT_SHIFT; - aml8726_wdt_soc_params.reset_cnt_mask = 0x3fffff << - AML_WDT_RESET_CNT_SHIFT; - break; - } - break; - case AML_SOC_HW_REV_M8B: - aml8726_wdt_soc_params.ctrl_cpu_mask = 0xf << - AML_WDT_CTRL_CPU_WDRESET_SHIFT; - aml8726_wdt_soc_params.ctrl_en = 1 << 19; - aml8726_wdt_soc_params.term_cnt_mask = 0x07ffff << - AML_WDT_CTRL_TERMINAL_CNT_SHIFT; - aml8726_wdt_soc_params.reset_cnt_mask = 0x07ffff << - AML_WDT_RESET_CNT_SHIFT; - break; - default: - aml8726_wdt_soc_params.ctrl_cpu_mask = 3 << - AML_WDT_CTRL_CPU_WDRESET_SHIFT; - aml8726_wdt_soc_params.ctrl_en = 1 << 22; - aml8726_wdt_soc_params.term_cnt_mask = 0x3fffff << - AML_WDT_CTRL_TERMINAL_CNT_SHIFT; - aml8726_wdt_soc_params.reset_cnt_mask = 0x3fffff << - AML_WDT_RESET_CNT_SHIFT; - break; - } - - /* - * Disable the watchdog. - */ - CSR_WRITE_4(sc, AML_WDT_CTRL_REG, - (CSR_READ_4(sc, AML_WDT_CTRL_REG) & ~(AML_WDT_CTRL_IRQ_EN | - AML_WDT_CTRL_EN))); - - /* - * Initialize the mutex prior to installing the interrupt handler - * in case of a spurious interrupt. - */ - AML_WDT_LOCK_INIT(sc); - - if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE, - aml8726_wdt_intr, NULL, sc, &sc->ih_cookie)) { - device_printf(dev, "could not setup interrupt handler\n"); - bus_release_resources(dev, aml8726_wdt_spec, sc->res); - AML_WDT_LOCK_DESTROY(sc); - return (ENXIO); - } - - aml8726_wdt_sc = sc; - - EVENTHANDLER_REGISTER(watchdog_list, aml8726_wdt_watchdog, sc, 0); - - return (0); -} - -static int -aml8726_wdt_detach(device_t dev) -{ - - return (EBUSY); -} - -static device_method_t aml8726_wdt_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aml8726_wdt_probe), - DEVMETHOD(device_attach, aml8726_wdt_attach), - DEVMETHOD(device_detach, aml8726_wdt_detach), - - DEVMETHOD_END -}; - -static driver_t aml8726_wdt_driver = { - "wdt", - aml8726_wdt_methods, - sizeof(struct aml8726_wdt_softc), -}; - -static devclass_t aml8726_wdt_devclass; - -EARLY_DRIVER_MODULE(wdt, simplebus, aml8726_wdt_driver, aml8726_wdt_devclass, - 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); - -void -cpu_reset(void) -{ - - /* Watchdog has not yet been initialized */ - if (aml8726_wdt_sc == NULL) - printf("Reset hardware has not yet been initialized.\n"); - else { - CSR_WRITE_4(aml8726_wdt_sc, AML_WDT_RESET_REG, 0); - CSR_WRITE_4(aml8726_wdt_sc, AML_WDT_CTRL_REG, - (AML_WDT_CTRL_CPU_WDRESET_MASK | AML_WDT_CTRL_EN | - (10 << AML_WDT_CTRL_TERMINAL_CNT_SHIFT))); - } - - while (1); -} Index: head/sys/arm/amlogic/aml8726/files.aml8726 =================================================================== --- head/sys/arm/amlogic/aml8726/files.aml8726 +++ head/sys/arm/amlogic/aml8726/files.aml8726 @@ -1,29 +0,0 @@ -#$FreeBSD$ - -arm/amlogic/aml8726/aml8726_l2cache.c standard - -arm/amlogic/aml8726/aml8726_machdep.c standard -arm/amlogic/aml8726/aml8726_mp.c optional smp -arm/amlogic/aml8726/aml8726_identsoc.c standard -arm/amlogic/aml8726/aml8726_ccm.c standard -arm/amlogic/aml8726/aml8726_clkmsr.c standard -arm/amlogic/aml8726/aml8726_pic.c optional aml_pic -arm/amlogic/aml8726/aml8726_rtc.c standard -arm/amlogic/aml8726/aml8726_timer.c standard -arm/amlogic/aml8726/aml8726_wdt.c standard - -# serial console for debugging early boot code -# also define SOCDEV_PA and SOCDEV_VA in std.aml8726 -#arm/amlogic/aml8726/aml8726_uart_console.c standard - -arm/amlogic/aml8726/aml8726_fb.c optional vt -arm/amlogic/aml8726/aml8726_gpio.c optional gpio -arm/amlogic/aml8726/aml8726_i2c.c optional iicbus -arm/amlogic/aml8726/aml8726_mmc.c optional mmc gpio -arm/amlogic/aml8726/aml8726_sdxc-m8.c optional mmc gpio -arm/amlogic/aml8726/aml8726_pinctrl.c optional fdt_pinctrl -#arm/amlogic/aml8726/aml8726_rng.c optional random -arm/amlogic/aml8726/uart_dev_aml8726.c optional uart -arm/amlogic/aml8726/aml8726_usb_phy-m3.c optional dwcotg usb gpio -arm/amlogic/aml8726/aml8726_usb_phy-m6.c optional dwcotg usb gpio -arm/amlogic/aml8726/aml8726_if_dwc.c optional dwc Index: head/sys/arm/amlogic/aml8726/std.aml8726 =================================================================== --- head/sys/arm/amlogic/aml8726/std.aml8726 +++ head/sys/arm/amlogic/aml8726/std.aml8726 @@ -1,25 +0,0 @@ -# $FreeBSD$ - -cpu CPU_CORTEXA -machine arm armv7 -makeoptions CONF_CFLAGS="-march=armv7a" - -# Physical memory starts at 0x80000000. We assume the kernel is loaded -# at 0x80100000 by u-boot (which doesn't support ubldr since it's missing -# CONFIG_API). The kernel must be supplied as a binary since u-boot is -# also missing CONFIG_CMD_ELF. -# -# -options KERNVIRTADDR=0xc0100000 # Used in ldscript.arm -makeoptions KERNVIRTADDR=0xc0100000 - -device fdt_pinctrl - -files "../amlogic/aml8726/files.aml8726" - -# Set all global interrupts to be edge triggered, active high. -options GIC_DEFAULT_ICFGR_INIT=0xffffffff - -#options EARLY_PRINTF -#options SOCDEV_PA=0xc8100000 -#options SOCDEV_VA=0xd8100000 Index: head/sys/arm/amlogic/aml8726/uart_dev_aml8726.c =================================================================== --- head/sys/arm/amlogic/aml8726/uart_dev_aml8726.c +++ head/sys/arm/amlogic/aml8726/uart_dev_aml8726.c @@ -1,771 +0,0 @@ -/*- - * Copyright 2013-2015 John Wehle - * 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. - */ - -/* - * Amlogic aml8726 UART driver. - * - * The current implementation only targets features common to all - * uarts. For example ... though UART A as a 128 byte FIFO, the - * others only have a 64 byte FIFO. - * - * Also, it's assumed that the USE_XTAL_CLK feature (available on - * the aml8726-m6 and later) has not been activated. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "uart_if.h" - -#undef uart_getreg -#undef uart_setreg - -#define uart_getreg(bas, reg) \ - bus_space_read_4((bas)->bst, (bas)->bsh, reg) -#define uart_setreg(bas, reg, value) \ - bus_space_write_4((bas)->bst, (bas)->bsh, reg, value) - -#define SIGCHG(c, i, s, d) \ - do { \ - if (c) { \ - i |= (i & s) ? s : s | d; \ - } else { \ - i = (i & s) ? (i & ~s) | d : i; \ - } \ - } while (0) - -static int -aml8726_uart_divisor(int rclk, int baudrate) -{ - int actual_baud, divisor; - int error; - - if (baudrate == 0) - return (0); - - /* integer version of (rclk / baudrate + .5) */ - divisor = ((rclk << 1) + baudrate) / (baudrate << 1); - if (divisor == 0) - return (0); - actual_baud = rclk / divisor; - - /* 10 times error in percent: */ - error = (((actual_baud - baudrate) * 2000) / baudrate + 1) >> 1; - - /* 3.0% maximum error tolerance: */ - if (error < -30 || error > 30) - return (0); - - return (divisor); -} - -static int -aml8726_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, - int parity) -{ - uint32_t cr; - uint32_t mr; - uint32_t nbr; - int divisor; - - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - - cr &= ~(AML_UART_CONTROL_DB_MASK | AML_UART_CONTROL_SB_MASK | - AML_UART_CONTROL_P_MASK); - - switch (databits) { - case 5: cr |= AML_UART_CONTROL_5_DB; break; - case 6: cr |= AML_UART_CONTROL_6_DB; break; - case 7: cr |= AML_UART_CONTROL_7_DB; break; - case 8: cr |= AML_UART_CONTROL_8_DB; break; - default: return (EINVAL); - } - - switch (stopbits) { - case 1: cr |= AML_UART_CONTROL_1_SB; break; - case 2: cr |= AML_UART_CONTROL_2_SB; break; - default: return (EINVAL); - } - - switch (parity) { - case UART_PARITY_EVEN: cr |= AML_UART_CONTROL_P_EVEN; - cr |= AML_UART_CONTROL_P_EN; - break; - - case UART_PARITY_ODD: cr |= AML_UART_CONTROL_P_ODD; - cr |= AML_UART_CONTROL_P_EN; - break; - - case UART_PARITY_NONE: break; - - default: return (EINVAL); - } - - /* Set baudrate. */ - if (baudrate > 0 && bas->rclk != 0) { - divisor = aml8726_uart_divisor(bas->rclk / 4, baudrate) - 1; - - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M6: - case AML_SOC_HW_REV_M8: - case AML_SOC_HW_REV_M8B: - if (divisor > (AML_UART_NEW_BAUD_RATE_MASK >> - AML_UART_NEW_BAUD_RATE_SHIFT)) - return (EINVAL); - - nbr = uart_getreg(bas, AML_UART_NEW_BAUD_REG); - nbr &= ~(AML_UART_NEW_BAUD_USE_XTAL_CLK | - AML_UART_NEW_BAUD_RATE_MASK); - nbr |= AML_UART_NEW_BAUD_RATE_EN | - (divisor << AML_UART_NEW_BAUD_RATE_SHIFT); - uart_setreg(bas, AML_UART_NEW_BAUD_REG, nbr); - - divisor = 0; - break; - default: - if (divisor > 0xffff) - return (EINVAL); - break; - } - - cr &= ~AML_UART_CONTROL_BAUD_MASK; - cr |= (divisor & AML_UART_CONTROL_BAUD_MASK); - - divisor >>= AML_UART_CONTROL_BAUD_WIDTH; - - mr = uart_getreg(bas, AML_UART_MISC_REG); - mr &= ~(AML_UART_MISC_OLD_RX_BAUD | - AML_UART_MISC_BAUD_EXT_MASK); - mr |= ((divisor << AML_UART_MISC_BAUD_EXT_SHIFT) & - AML_UART_MISC_BAUD_EXT_MASK); - uart_setreg(bas, AML_UART_MISC_REG, mr); - } - - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - - return (0); -} - -/* - * Low-level UART interface. - */ - -static int -aml8726_uart_probe(struct uart_bas *bas) -{ - - return (0); -} - -static void -aml8726_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, - int parity) -{ - uint32_t cr; - uint32_t mr; - - (void)aml8726_uart_param(bas, baudrate, databits, stopbits, parity); - - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - /* Disable all interrupt sources. */ - cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); - /* Reset the transmitter and receiver. */ - cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); - /* Enable the transmitter and receiver. */ - cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN); - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - - /* Clear RX FIFO level for generating interrupts. */ - mr = uart_getreg(bas, AML_UART_MISC_REG); - mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; - uart_setreg(bas, AML_UART_MISC_REG, mr); - uart_barrier(bas); - - /* Ensure the reset bits are clear. */ - cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); -} - -static void -aml8726_uart_term(struct uart_bas *bas) -{ -} - -static void -aml8726_uart_putc(struct uart_bas *bas, int c) -{ - - while ((uart_getreg(bas, AML_UART_STATUS_REG) & - AML_UART_STATUS_TX_FIFO_FULL) != 0) - cpu_spinwait(); - - uart_setreg(bas, AML_UART_WFIFO_REG, c); - uart_barrier(bas); -} - -static int -aml8726_uart_rxready(struct uart_bas *bas) -{ - - return ((uart_getreg(bas, AML_UART_STATUS_REG) & - AML_UART_STATUS_RX_FIFO_EMPTY) == 0 ? 1 : 0); -} - -static int -aml8726_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) -{ - int c; - - uart_lock(hwmtx); - - while ((uart_getreg(bas, AML_UART_STATUS_REG) & - AML_UART_STATUS_RX_FIFO_EMPTY) != 0) { - uart_unlock(hwmtx); - DELAY(4); - uart_lock(hwmtx); - } - - c = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff; - - uart_unlock(hwmtx); - - return (c); -} - -struct uart_ops aml8726_uart_ops = { - .probe = aml8726_uart_probe, - .init = aml8726_uart_init, - .term = aml8726_uart_term, - .putc = aml8726_uart_putc, - .rxready = aml8726_uart_rxready, - .getc = aml8726_uart_getc, -}; - -static unsigned int -aml8726_uart_bus_clk(phandle_t node) -{ - pcell_t prop; - ssize_t len; - phandle_t clk_node; - - len = OF_getencprop(node, "clocks", &prop, sizeof(prop)); - if ((len / sizeof(prop)) != 1 || prop == 0 || - (clk_node = OF_node_from_xref(prop)) == 0) - return (0); - - len = OF_getencprop(clk_node, "clock-frequency", &prop, sizeof(prop)); - if ((len / sizeof(prop)) != 1 || prop == 0) - return (0); - - return ((unsigned int)prop); -} - -static int -aml8726_uart_bus_probe(struct uart_softc *sc) -{ - int error; - - error = aml8726_uart_probe(&sc->sc_bas); - if (error) - return (error); - - sc->sc_rxfifosz = 64; - sc->sc_txfifosz = 64; - sc->sc_hwiflow = 1; - sc->sc_hwoflow = 1; - - device_set_desc(sc->sc_dev, "Amlogic aml8726 UART"); - - return (0); -} - -static int -aml8726_uart_bus_getsig(struct uart_softc *sc) -{ - uint32_t new, old, sig; - - /* - * Treat DSR, DCD, and CTS as always on. - */ - - do { - old = sc->sc_hwsig; - sig = old; - SIGCHG(1, sig, SER_DSR, SER_DDSR); - SIGCHG(1, sig, SER_DCD, SER_DDCD); - SIGCHG(1, sig, SER_CTS, SER_DCTS); - new = sig & ~SER_MASK_DELTA; - } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); - - return (sig); -} - -static int -aml8726_uart_bus_setsig(struct uart_softc *sc, int sig) -{ - uint32_t new, old; - - do { - old = sc->sc_hwsig; - new = old; - if (sig & SER_DDTR) { - SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR); - } - if (sig & SER_DRTS) { - SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS); - } - } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); - - return (0); -} - -static int -aml8726_uart_bus_attach(struct uart_softc *sc) -{ - struct uart_bas *bas; - uint32_t cr; - uint32_t mr; - - bas = &sc->sc_bas; - - bas->rclk = aml8726_uart_bus_clk(ofw_bus_get_node(sc->sc_dev)); - - if (bas->rclk == 0) { - device_printf(sc->sc_dev, "missing clocks attribute in FDT\n"); - return (ENXIO); - } - - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - /* Disable all interrupt sources. */ - cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); - /* Ensure the reset bits are clear. */ - cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); - - /* - * Reset the transmitter and receiver only if not acting as a - * console, otherwise it means that: - * - * 1) aml8726_uart_init was already called which did the reset - * - * 2) there may be console bytes sitting in the transmit fifo - */ - if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) - ; - else - cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); - - /* Default to two wire mode. */ - cr |= AML_UART_CONTROL_TWO_WIRE_EN; - /* Enable the transmitter and receiver. */ - cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN); - /* Reset error bits. */ - cr |= AML_UART_CONTROL_CLR_ERR; - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - - /* Set FIFO levels for generating interrupts. */ - mr = uart_getreg(bas, AML_UART_MISC_REG); - mr &= ~AML_UART_MISC_XMIT_IRQ_CNT_MASK; - mr |= (0 << AML_UART_MISC_XMIT_IRQ_CNT_SHIFT); - mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; - mr |= (1 << AML_UART_MISC_RECV_IRQ_CNT_SHIFT); - uart_setreg(bas, AML_UART_MISC_REG, mr); - uart_barrier(bas); - - aml8726_uart_bus_getsig(sc); - - /* Ensure the reset bits are clear. */ - cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); - cr &= ~AML_UART_CONTROL_CLR_ERR; - /* Enable the receive interrupt. */ - cr |= AML_UART_CONTROL_RX_INT_EN; - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - - return (0); -} - -static int -aml8726_uart_bus_detach(struct uart_softc *sc) -{ - struct uart_bas *bas; - uint32_t cr; - uint32_t mr; - - bas = &sc->sc_bas; - - /* Disable all interrupt sources. */ - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - - /* Clear RX FIFO level for generating interrupts. */ - mr = uart_getreg(bas, AML_UART_MISC_REG); - mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; - uart_setreg(bas, AML_UART_MISC_REG, mr); - uart_barrier(bas); - - return (0); -} - -static int -aml8726_uart_bus_flush(struct uart_softc *sc, int what) -{ - struct uart_bas *bas; - uint32_t cr; - - bas = &sc->sc_bas; - uart_lock(sc->sc_hwmtx); - - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - if (what & UART_FLUSH_TRANSMITTER) - cr |= AML_UART_CONTROL_TX_RST; - if (what & UART_FLUSH_RECEIVER) - cr |= AML_UART_CONTROL_RX_RST; - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - - /* Ensure the reset bits are clear. */ - cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - - uart_unlock(sc->sc_hwmtx); - - return (0); -} - -static int -aml8726_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) -{ - struct uart_bas *bas; - int baudrate, divisor, error; - uint32_t cr, mr, nbr; - - bas = &sc->sc_bas; - uart_lock(sc->sc_hwmtx); - - error = 0; - switch (request) { - case UART_IOCTL_BAUD: - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - cr &= AML_UART_CONTROL_BAUD_MASK; - - mr = uart_getreg(bas, AML_UART_MISC_REG); - mr &= AML_UART_MISC_BAUD_EXT_MASK; - - divisor = ((mr >> AML_UART_MISC_BAUD_EXT_SHIFT) << - AML_UART_CONTROL_BAUD_WIDTH) | cr; - - switch (aml8726_soc_hw_rev) { - case AML_SOC_HW_REV_M6: - case AML_SOC_HW_REV_M8: - case AML_SOC_HW_REV_M8B: - nbr = uart_getreg(bas, AML_UART_NEW_BAUD_REG); - if ((nbr & AML_UART_NEW_BAUD_RATE_EN) != 0) { - divisor = (nbr & AML_UART_NEW_BAUD_RATE_MASK) >> - AML_UART_NEW_BAUD_RATE_SHIFT; - } - break; - default: - break; - } - - baudrate = bas->rclk / 4 / (divisor + 1); - if (baudrate > 0) - *(int*)data = baudrate; - else - error = ENXIO; - break; - - case UART_IOCTL_IFLOW: - case UART_IOCTL_OFLOW: - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - if (data) - cr &= ~AML_UART_CONTROL_TWO_WIRE_EN; - else - cr |= AML_UART_CONTROL_TWO_WIRE_EN; - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - break; - - default: - error = EINVAL; - break; - } - - uart_unlock(sc->sc_hwmtx); - - return (error); -} - -static int -aml8726_uart_bus_ipend(struct uart_softc *sc) -{ - struct uart_bas *bas; - int ipend; - uint32_t sr; - uint32_t cr; - - bas = &sc->sc_bas; - uart_lock(sc->sc_hwmtx); - - ipend = 0; - sr = uart_getreg(bas, AML_UART_STATUS_REG); - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - - if ((sr & AML_UART_STATUS_RX_FIFO_OVERFLOW) != 0) - ipend |= SER_INT_OVERRUN; - - if ((sr & AML_UART_STATUS_TX_FIFO_EMPTY) != 0 && - (cr & AML_UART_CONTROL_TX_INT_EN) != 0) { - ipend |= SER_INT_TXIDLE; - - cr &= ~AML_UART_CONTROL_TX_INT_EN; - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - } - - if ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) - ipend |= SER_INT_RXREADY; - - uart_unlock(sc->sc_hwmtx); - - return (ipend); -} - -static int -aml8726_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, - int stopbits, int parity) -{ - struct uart_bas *bas; - int error; - - bas = &sc->sc_bas; - uart_lock(sc->sc_hwmtx); - - error = aml8726_uart_param(bas, baudrate, databits, stopbits, parity); - - uart_unlock(sc->sc_hwmtx); - - return (error); -} - -static int -aml8726_uart_bus_receive(struct uart_softc *sc) -{ - struct uart_bas *bas; - int xc; - uint32_t sr; - - bas = &sc->sc_bas; - uart_lock(sc->sc_hwmtx); - - sr = uart_getreg(bas, AML_UART_STATUS_REG); - while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) { - if (uart_rx_full(sc)) { - sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; - break; - } - xc = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff; - if (sr & AML_UART_STATUS_FRAME_ERR) - xc |= UART_STAT_FRAMERR; - if (sr & AML_UART_STATUS_PARITY_ERR) - xc |= UART_STAT_PARERR; - uart_rx_put(sc, xc); - sr = uart_getreg(bas, AML_UART_STATUS_REG); - } - /* Discard everything left in the RX FIFO. */ - while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) { - (void)uart_getreg(bas, AML_UART_RFIFO_REG); - sr = uart_getreg(bas, AML_UART_STATUS_REG); - } - /* Reset error bits */ - if ((sr & (AML_UART_STATUS_FRAME_ERR | AML_UART_STATUS_PARITY_ERR)) != 0) { - uart_setreg(bas, AML_UART_CONTROL_REG, - (uart_getreg(bas, AML_UART_CONTROL_REG) | - AML_UART_CONTROL_CLR_ERR)); - uart_barrier(bas); - uart_setreg(bas, AML_UART_CONTROL_REG, - (uart_getreg(bas, AML_UART_CONTROL_REG) & - ~AML_UART_CONTROL_CLR_ERR)); - uart_barrier(bas); - } - - uart_unlock(sc->sc_hwmtx); - - return (0); -} - -static int -aml8726_uart_bus_transmit(struct uart_softc *sc) -{ - struct uart_bas *bas; - int i; - uint32_t cr; - - bas = &sc->sc_bas; - uart_lock(sc->sc_hwmtx); - - /* - * Wait for sufficient space since aml8726_uart_putc - * may have been called after SER_INT_TXIDLE occurred. - */ - while ((uart_getreg(bas, AML_UART_STATUS_REG) & - AML_UART_STATUS_TX_FIFO_EMPTY) == 0) - cpu_spinwait(); - - for (i = 0; i < sc->sc_txdatasz; i++) { - uart_setreg(bas, AML_UART_WFIFO_REG, sc->sc_txbuf[i]); - uart_barrier(bas); - } - - sc->sc_txbusy = 1; - - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - cr |= AML_UART_CONTROL_TX_INT_EN; - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - - uart_unlock(sc->sc_hwmtx); - - return (0); -} - -static void -aml8726_uart_bus_grab(struct uart_softc *sc) -{ - struct uart_bas *bas; - uint32_t cr; - - /* - * Disable the receive interrupt to avoid a race between - * aml8726_uart_getc and aml8726_uart_bus_receive which - * can trigger: - * - * panic: bad stray interrupt - * - * due to the RX FIFO receiving a character causing an - * interrupt which gets serviced after aml8726_uart_getc - * has been called (meaning the RX FIFO is now empty). - */ - - bas = &sc->sc_bas; - uart_lock(sc->sc_hwmtx); - - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - cr &= ~AML_UART_CONTROL_RX_INT_EN; - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - - uart_unlock(sc->sc_hwmtx); -} - -static void -aml8726_uart_bus_ungrab(struct uart_softc *sc) -{ - struct uart_bas *bas; - uint32_t cr; - uint32_t mr; - - /* - * The RX FIFO level being set indicates that the device - * is currently attached meaning the receive interrupt - * should be enabled. - */ - - bas = &sc->sc_bas; - uart_lock(sc->sc_hwmtx); - - mr = uart_getreg(bas, AML_UART_MISC_REG); - mr &= AML_UART_MISC_RECV_IRQ_CNT_MASK; - - if (mr != 0) { - cr = uart_getreg(bas, AML_UART_CONTROL_REG); - cr |= AML_UART_CONTROL_RX_INT_EN; - uart_setreg(bas, AML_UART_CONTROL_REG, cr); - uart_barrier(bas); - } - - uart_unlock(sc->sc_hwmtx); -} - -static kobj_method_t aml8726_uart_methods[] = { - KOBJMETHOD(uart_probe, aml8726_uart_bus_probe), - KOBJMETHOD(uart_attach, aml8726_uart_bus_attach), - KOBJMETHOD(uart_detach, aml8726_uart_bus_detach), - KOBJMETHOD(uart_flush, aml8726_uart_bus_flush), - KOBJMETHOD(uart_getsig, aml8726_uart_bus_getsig), - KOBJMETHOD(uart_setsig, aml8726_uart_bus_setsig), - KOBJMETHOD(uart_ioctl, aml8726_uart_bus_ioctl), - KOBJMETHOD(uart_ipend, aml8726_uart_bus_ipend), - KOBJMETHOD(uart_param, aml8726_uart_bus_param), - KOBJMETHOD(uart_receive, aml8726_uart_bus_receive), - KOBJMETHOD(uart_transmit, aml8726_uart_bus_transmit), - KOBJMETHOD(uart_grab, aml8726_uart_bus_grab), - KOBJMETHOD(uart_ungrab, aml8726_uart_bus_ungrab), - { 0, 0 } -}; - -struct uart_class uart_aml8726_class = { - "uart", - aml8726_uart_methods, - sizeof(struct uart_softc), - .uc_ops = &aml8726_uart_ops, - .uc_range = 24, - .uc_rclk = 0, - .uc_rshift = 0 -}; - -static struct ofw_compat_data compat_data[] = { - { "amlogic,meson-uart", (uintptr_t)&uart_aml8726_class }, - { NULL, (uintptr_t)NULL } -}; -UART_FDT_CLASS_AND_DEVICE(compat_data);