--- /dev/null
+/* $OpenBSD: am335x.c,v 1.7 2014/03/18 07:34:17 syl Exp $ */
+
+/*
+ * Copyright (c) 2011 Uwe Stuehler <uwe@openbsd.org>
+ * Copyright (c) 2013 Raphael Graf <r@undefined.ch>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <machine/bus.h>
+
+#include <armv7/armv7/armv7var.h>
+
+#define PRCM_SIZE 0x2000
+#define PRCM_ADDR 0x44E00000
+
+#define SCM_SIZE 0x2000
+#define SCM_ADDR 0x44E10000
+
+#define INTC_SIZE 0x300
+#define INTC_ADDR 0x48200000
+
+#define DMTIMERx_SIZE 0x80
+#define DMTIMER0_ADDR 0x44E05000
+#define DMTIMER1_ADDR 0x44E31000 /* 1MS */
+#define DMTIMER2_ADDR 0x48040000
+#define DMTIMER3_ADDR 0x48042000
+#define DMTIMER4_ADDR 0x48044000
+#define DMTIMER5_ADDR 0x48046000
+#define DMTIMER6_ADDR 0x48048000
+#define DMTIMER7_ADDR 0x4804A000
+#define DMTIMER0_IRQ 66
+#define DMTIMER1_IRQ 67
+#define DMTIMER2_IRQ 68
+#define DMTIMER3_IRQ 69
+#define DMTIMER4_IRQ 92
+#define DMTIMER5_IRQ 93
+#define DMTIMER6_IRQ 94
+#define DMTIMER7_IRQ 95
+
+#define WD_SIZE 0x80
+#define WD_ADDR 0x44E35000
+#define WD_IRQ 91
+
+#define GPIOx_SIZE 0x200
+#define GPIO0_ADDR 0x44E07000
+#define GPIO1_ADDR 0x4804C000
+#define GPIO2_ADDR 0x481AC000
+#define GPIO3_ADDR 0x481AE000
+#define GPIO0_IRQ 96
+#define GPIO1_IRQ 98
+#define GPIO2_IRQ 32
+#define GPIO3_IRQ 62
+
+#define TPCC_SIZE 0x100000
+#define TPCC_ADDR 0x49000000
+#define TPTC0_ADDR 0x49800000
+#define TPTC1_ADDR 0x49900000
+#define TPTC2_ADDR 0x49a00000
+#define EDMACOMP_IRQ 12
+#define EDMAMPERR_IRQ 13
+#define EDMAERR_IRQ 14
+
+#define UARTx_SIZE 0x90
+#define UART0_ADDR 0x44E09000
+#define UART1_ADDR 0x48022000
+#define UART2_ADDR 0x48024000
+#define UART3_ADDR 0x481A6000
+#define UART4_ADDR 0x481A8000
+#define UART5_ADDR 0x481AA000
+#define UART0_IRQ 72
+#define UART1_IRQ 73
+#define UART2_IRQ 74
+#define UART3_IRQ 44
+#define UART4_IRQ 45
+#define UART5_IRQ 46
+
+#define HSMMCx_SIZE 0x200
+#define HSMMC0_ADDR 0x48060100
+#define HSMMC1_ADDR 0x481d8100
+#define HSMMC0_IRQ 64
+#define HSMMC1_IRQ 28
+
+#define CPSW_SIZE 0x4000
+#define CPSW_ADDR 0x4A100000
+#define CPSW_IRQ 40
+
+#define IICx_SIZE 0x1000
+#define IIC0_ADDR 0x44e0b000
+#define IIC1_ADDR 0x4802a000
+#define IIC2_ADDR 0x4819c000
+#define IIC0_IRQ 70
+#define IIC1_IRQ 71
+#define IIC2_IRQ 30
+
+struct armv7_dev am335x_devs[] = {
+
+ /*
+ * Power, Reset and Clock Manager
+ */
+
+ { .name = "prcm",
+ .unit = 0,
+ .mem = { { PRCM_ADDR, PRCM_SIZE } },
+ },
+
+ /*
+ * System Control Module
+ */
+
+ { .name = "sitaracm",
+ .unit = 0,
+ .mem = { { SCM_ADDR, SCM_SIZE } },
+ },
+
+ /*
+ * Interrupt Controller
+ */
+
+ { .name = "intc",
+ .unit = 0,
+ .mem = { { INTC_ADDR, INTC_SIZE } },
+ },
+
+ /*
+ * EDMA Controller
+ */
+ { .name = "edma",
+ .unit = 0,
+ .mem = { { TPCC_ADDR, TPCC_SIZE } },
+ .irq = { EDMACOMP_IRQ }
+ },
+
+ /*
+ * General Purpose Timers
+ */
+
+ { .name = "dmtimer",
+ .unit = 0,
+ .mem = { { DMTIMER2_ADDR, DMTIMERx_SIZE } },
+ .irq = { DMTIMER2_IRQ }
+ },
+
+ { .name = "dmtimer",
+ .unit = 1,
+ .mem = { { DMTIMER3_ADDR, DMTIMERx_SIZE } },
+ .irq = { DMTIMER3_IRQ }
+ },
+
+ /*
+ * Watchdog Timer
+ */
+
+ { .name = "omdog",
+ .unit = 0,
+ .mem = { { WD_ADDR, WD_SIZE } }
+ },
+
+ /*
+ * UART
+ */
+
+ { .name = "com",
+ .unit = 0,
+ .mem = { { UART0_ADDR, UARTx_SIZE } },
+ .irq = { UART0_IRQ }
+ },
+
+ /*
+ * GPIO
+ */
+
+ { .name = "omgpio",
+ .unit = 0,
+ .mem = { { GPIO0_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO0_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 1,
+ .mem = { { GPIO1_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO1_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 2,
+ .mem = { { GPIO2_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO2_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 3,
+ .mem = { { GPIO3_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO3_IRQ }
+ },
+
+ /*
+ * IIC
+ */
+
+ { .name = "tiiic",
+ .unit = 0,
+ .mem = { { IIC0_ADDR, IICx_SIZE } },
+ .irq = { IIC0_IRQ }
+ },
+
+ { .name = "tiiic",
+ .unit = 1,
+ .mem = { { IIC1_ADDR, IICx_SIZE } },
+ .irq = { IIC1_IRQ }
+ },
+
+ { .name = "tiiic",
+ .unit = 2,
+ .mem = { { IIC2_ADDR, IICx_SIZE } },
+ .irq = { IIC2_IRQ }
+ },
+
+ /*
+ * MMC
+ */
+
+ { .name = "ommmc",
+ .unit = 0,
+ .mem = { { HSMMC0_ADDR, HSMMCx_SIZE } },
+ .irq = { HSMMC0_IRQ }
+ },
+
+ { .name = "ommmc",
+ .unit = 1,
+ .mem = { { HSMMC1_ADDR, HSMMCx_SIZE } },
+ .irq = { HSMMC1_IRQ }
+ },
+
+ /* cpsw Ethernet */
+ { .name = "cpsw",
+ .unit = 0,
+ .mem = { { CPSW_ADDR, CPSW_SIZE } },
+ .irq = { CPSW_IRQ }
+ },
+
+ /* Terminator */
+ { .name = NULL,
+ .unit = 0
+ }
+};
+
+void
+am335x_init(void)
+{
+ armv7_set_devs(am335x_devs);
+}
--- /dev/null
+/* $OpenBSD: am335x_cm_padconf.c,v 1.1 2013/09/04 14:38:30 patrick Exp $ */
+/* $NetBSD: am335x_cm_padconf.c,v 1.2 2013/05/06 18:53:40 rkujawa Exp $ */
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion@FreeBSD.org>
+ * 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 <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/gpio.h>
+#include <armv7/omap/sitara_cm.h>
+
+#define _PIN(r, b, gp, gm, m0, m1, m2, m3, m4, m5, m6, m7) \
+ { .reg_off = r, \
+ .gpio_pin = gp, \
+ .gpio_mode = gm, \
+ .ballname = b, \
+ .muxmodes[0] = m0, \
+ .muxmodes[1] = m1, \
+ .muxmodes[2] = m2, \
+ .muxmodes[3] = m3, \
+ .muxmodes[4] = m4, \
+ .muxmodes[5] = m5, \
+ .muxmodes[6] = m6, \
+ .muxmodes[7] = m7, \
+ }
+
+#define SLEWCTRL (0x01 << 6) /* faster(0) or slower(1) slew rate. */
+#define RXACTIVE (0x01 << 5) /* Input enable value for the Pad */
+#define PULLTYPESEL (0x01 << 4) /* Pad pullup/pulldown type selection */
+#define PULLUDEN (0x01 << 3) /* Pullup/pulldown disabled */
+
+#define PADCONF_OUTPUT (0)
+#define PADCONF_OUTPUT_PULLUP (PULLTYPESEL)
+#define PADCONF_INPUT (RXACTIVE | PULLUDEN)
+#define PADCONF_INPUT_PULLUP (RXACTIVE | PULLTYPESEL)
+#define PADCONF_INPUT_PULLDOWN (RXACTIVE)
+#define PADCONF_INPUT_PULLUP_SLOW (PADCONF_INPUT_PULLUP | SLEWCTRL)
+
+const struct sitara_cm_padstate ti_padstate_devmap[] = {
+ {"output", PADCONF_OUTPUT },
+ {"output_pullup", PADCONF_OUTPUT_PULLUP },
+ {"input", PADCONF_INPUT },
+ {"input_pulldown", PADCONF_INPUT_PULLDOWN },
+ {"input_pullup", PADCONF_INPUT_PULLUP },
+ {"i2c", PADCONF_INPUT_PULLUP_SLOW },
+ { .state = NULL }
+};
+
+const struct sitara_cm_padconf ti_padconf_devmap[] = {
+ _PIN(0x800, "GPMC_AD0", 32, 7,"gpmc_ad0", "mmc1_dat0", NULL, NULL, NULL, NULL, NULL, "gpio1_0"),
+ _PIN(0x804, "GPMC_AD1", 33, 7,"gpmc_ad1", "mmc1_dat1", NULL, NULL, NULL, NULL, NULL, "gpio1_1"),
+ _PIN(0x808, "GPMC_AD2", 34, 7,"gpmc_ad2", "mmc1_dat2", NULL, NULL, NULL, NULL, NULL, "gpio1_2"),
+ _PIN(0x80C, "GPMC_AD3", 35, 7,"gpmc_ad3", "mmc1_dat3", NULL, NULL, NULL, NULL, NULL, "gpio1_3"),
+ _PIN(0x810, "GPMC_AD4", 36, 7,"gpmc_ad4", "mmc1_dat4", NULL, NULL, NULL, NULL, NULL, "gpio1_4"),
+ _PIN(0x814, "GPMC_AD5", 37, 7,"gpmc_ad5", "mmc1_dat5", NULL, NULL, NULL, NULL, NULL, "gpio1_5"),
+ _PIN(0x818, "GPMC_AD6", 38, 7,"gpmc_ad6", "mmc1_dat6", NULL, NULL, NULL, NULL, NULL, "gpio1_6"),
+ _PIN(0x81C, "GPMC_AD7", 39, 7,"gpmc_ad7", "mmc1_dat7", NULL, NULL, NULL, NULL, NULL, "gpio1_7"),
+ _PIN(0x820, "GPMC_AD8", 22, 7, "gpmc_ad8", "lcd_data23", "mmc1_dat0", "mmc2_dat4", "ehrpwm2A", NULL, NULL, "gpio0_22"),
+ _PIN(0x824, "GPMC_AD9", 23, 7, "gpmc_ad9", "lcd_data22", "mmc1_dat1", "mmc2_dat5", "ehrpwm2B", NULL, NULL, "gpio0_23"),
+ _PIN(0x828, "GPMC_AD10", 26, 7, "gpmc_ad10", "lcd_data21", "mmc1_dat2", "mmc2_dat6", "ehrpwm2_tripzone_in", NULL, NULL, "gpio0_26"),
+ _PIN(0x82C, "GPMC_AD11", 27, 7, "gpmc_ad11", "lcd_data20", "mmc1_dat3", "mmc2_dat7", "ehrpwm0_synco", NULL, NULL, "gpio0_27"),
+ _PIN(0x830, "GPMC_AD12", 44, 7, "gpmc_ad12", "lcd_data19", "mmc1_dat4", "mmc2_dat0", "eQEP2A_in", "pr1_mii0_txd2", "pr1_pru0_pru_r30_14", "gpio1_12"),
+ _PIN(0x834, "GPMC_AD13", 45, 7, "gpmc_ad13", "lcd_data18", "mmc1_dat5", "mmc2_dat1", "eQEP2B_in", "pr1_mii0_txd1", "pr1_pru0_pru_r30_15", "gpio1_13"),
+ _PIN(0x838, "GPMC_AD14", 46, 7, "gpmc_ad14", "lcd_data17", "mmc1_dat6", "mmc2_dat2", "eQEP2_index", "pr1_mii0_txd0", "pr1_pru0_pru_r31_14", "gpio1_14"),
+ _PIN(0x83C, "GPMC_AD15", 47, 7, "gpmc_ad15", "lcd_data16", "mmc1_dat7", "mmc2_dat3", "eQEP2_strobe", "pr1_ecap0_ecap_capin_apwm_o", "pr1_pru0_pru_r31_15", "gpio1_15"),
+ _PIN(0x840, "GPMC_A0", 48, 7, "gpmc_a0", "gmii2_txen", "rgmii2_tctl", "rmii2_txen", "gpmc_a16", "pr1_mii_mt1_clk", "ehrpwm1_tripzone_input", "gpio1_16"),
+ _PIN(0x844, "GPMC_A1", 49, 7, "gpmc_a1", "gmii2_rxdv", "rgmii2_rctl", "mmc2_dat0", "gpmc_a17", "pr1_mii1_txd3", "ehrpwm0_synco", "gpio1_17"),
+ _PIN(0x848, "GPMC_A2", 50, 7, "gpmc_a2", "gmii2_txd3", "rgmii2_td3", "mmc2_dat1", "gpmc_a18", "pr1_mii1_txd2", "ehrpwm1A", "gpio1_18"),
+ _PIN(0x84C, "GPMC_A3", 51, 7, "gpmc_a3", "gmii2_txd2", "rgmii2_td2", "mmc2_dat2", "gpmc_a19", "pr1_mii1_txd1", "ehrpwm1B", "gpio1_19"),
+ _PIN(0x850, "GPMC_A4", 52, 7, "gpmc_a4", "gmii2_txd1", "rgmii2_td1", "rmii2_tdx1", "gpmc_a20", "pr1_mii1_txd0", "eQEP1A_in", "gpio1_20"),
+ _PIN(0x854, "GPMC_A5", 53, 7, "gpmc_a5", "gmii2_txd0", "rgmii2_td0", "rmii2_txd0", "gpmc_a21", "pr1_mii1_rxd3", "eQEP1B_in", "gpio1_21"),
+ _PIN(0x858, "GPMC_A6", 54, 7, "gpmc_a6", "gmii2_txclk", "rgmii2_tclk", "mmc2_dat4", "gpmc_a22", "pr1_mii1_rxd2", "eQEP1_index", "gpio1_22"),
+ _PIN(0x85C, "GPMC_A7", 55, 7, "gpmc_a7", "gmii2_rxclk", "rgmii2_rclk", "mmc2_dat5", "gpmc_a23", "pr1_mii1_rxd1", "eQEP1_strobe", "gpio1_23"),
+ _PIN(0x860, "GPMC_A8", 56, 7, "gpmc_a8", "gmii2_rxd3", "rgmii2_rd3", "mmc2_dat6", "gpmc_a24", "pr1_mii1_rxd0", "mcasp0_aclkx", "gpio1_24"),
+ _PIN(0x864, "GPMC_A9", 57, 7, "gmpc_a9", "gmii2_rxd2", "rgmii2_rd2", "mmc2_dat7 / rmii2_crs_dv", "gpmc_a25", "pr1_mii_mr1_clk", "mcasp0_fsx", "gpio1_25"),
+ _PIN(0x868, "GPMC_A10", 58, 7, "gmpc_a10", "gmii2_rxd1", "rgmii2_rd1", "rmii2_rxd1", "gpmc_a26", "pr1_mii1_rxdv", "mcasp0_arx0", "gpio1_26"),
+ _PIN(0x86C, "GPMC_A11", 59, 7, "gmpc_a11", "gmii2_rxd0", "rgmii2_rd0", "rmii2_rxd0", "gpmc_a27", "pr1_mii1_rxer", "mcasp0_axr1", "gpio1_27"),
+ _PIN(0x870, "GPMC_WAIT0", 30, 7, "gpmc_wait0", "gmii2_crs", "gpmc_csn4", "rmii2_crs_dv", "mmc1_sdcd", "pr1_mii1_col", "uart4_rxd", "gpio0_30"),
+ _PIN(0x874, "GPMC_WPn", 31, 7, "gpmc_wpn", "gmii2_rxerr", "gpmc_csn5", "rmii2_rxerr", "mmc2_sdcd", "pr1_mii1_txen", "uart4_txd", "gpio0_31"),
+ _PIN(0x878, "GPMC_BEn1", 60, 7, "gpmc_be1n", "gmii2_col", "gmpc_csn6","mmc2_dat3", "gpmc_dir", "pr1_mii1_rxlink", "mcasp0_aclkr", "gpio1_28"),
+ _PIN(0x87c, "GPMC_CSn0", 61, 7, "gpmc_csn0", NULL, NULL, NULL, NULL, NULL, NULL, "gpio1_29"),
+ _PIN(0x880, "GPMC_CSn1", 62, 7, "gpmc_csn1", "gpmc_clk", "mmc1_clk", "pr1_edio_data_in6", "pr1_edio_data_out6", "pr1_pru1_pru_r30_12", "pr1_pru1_pru_r31_12", "gpio1_30"),
+ _PIN(0x884, "GPMC_CSn2", 63, 7, "gpmc_csn2", "gpmc_be1n", "mmc1_cmd", "pr1_edio_data_in7", "pr1_edio_data_out7", "pr1_pru1_pru_r30_13", "pr1_pru1_pru_r31_13", "gpio1_31"),
+ _PIN(0x888, "GPMC_CSn3", 64, 7, "gpmc_csn3", "gpmc_a3", "rmii2_crs_dv", "mmc2_cmd", "pr1_mii0_crs", "pr1_mdio_data", "EMU4", "gpio2_0"),
+ _PIN(0x88c, "GPMC_CLK", 65, 7, "gpmc_clk", "lcd_memory_clk", "gpmc_wait1", "mmc2_clk", "pr1_mii1_crs", "pr1_mdio_mdclk", "mcasp0_fsr", "gpio2_1"),
+ _PIN(0x890, "GPMC_ADVn_ALE", 66, 7, "gpmc_advn_ale", NULL, "timer4", NULL, NULL, NULL, NULL, "gpio2_2"),
+ _PIN(0x894, "GPMC_OEn_REn", 67, 7, "gpmc_oen_ren", NULL, "timer7", NULL, NULL, NULL, NULL, "gpio2_3"),
+ _PIN(0x898, "GPMC_WEn", 68, 7, "gpmc_wen", NULL, "timer6", NULL, NULL, NULL, NULL, "gpio2_4"),
+ _PIN(0x89c, "GPMC_BEn0_CLE", 67, 7, "gpmc_ben0_cle", NULL, "timer5", NULL, NULL, NULL, NULL, "gpio2_5"),
+ _PIN(0x8a0, "LCD_DATA0", 68, 7, "lcd_data0", "gpmc_a0", "pr1_mii_mt0_clk", "ehrpwm2A", NULL, "pr1_pru1_pru_r30_0", "pr1_pru1_pru_r31_0", "gpio2_6"),
+ _PIN(0x8a4, "LCD_DATA1", 69, 7, "lcd_data1", "gpmc_a1", "pr1_mii0_txen", "ehrpwm2B", NULL, "pr1_pru1_pru_r30_1", "pr1_pru1_pru_r31_1", "gpio2_7"),
+ _PIN(0x8a8, "LCD_DATA2", 70, 7, "lcd_data2", "gpmc_a2", "pr1_mii0_txd3", "ehrpwm2_tripzone_input", NULL, "pr1_pru1_pru_r30_2", "pr1_pru1_pru_r31_2", "gpio2_8"),
+ _PIN(0x8ac, "LCD_DATA3", 71, 7, "lcd_data3", "gpmc_a3", "pr1_mii0_txd2", "ehrpwm0_synco", NULL, "pr1_pru1_pru_r30_3", "pr1_pru1_pru_r31_3", "gpio2_9"),
+ _PIN(0x8b0, "LCD_DATA4", 72, 7, "lcd_data4", "gpmc_a4", "pr1_mii0_txd1", "eQEP2A_in", NULL, "pr1_pru1_pru_r30_4", "pr1_pru1_pru_r31_4", "gpio2_10"),
+ _PIN(0x8b4, "LCD_DATA5", 73, 7, "lcd_data5", "gpmc_a5", "pr1_mii0_txd0", "eQEP2B_in", NULL, "pr1_pru1_pru_r30_5", "pr1_pru1_pru_r31_5", "gpio2_11"),
+ _PIN(0x8b8, "LCD_DATA6", 74, 7, "lcd_data6", "gpmc_a6", "pr1_edio_data_in6", "eQEP2_index", "pr1_edio_data_out6", "pr1_pru1_pru_r30_6", "pr1_pru1_pru_r31_6", "gpio2_12"),
+ _PIN(0x8bc, "LCD_DATA7", 75, 7, "lcd_data7", "gpmc_a7", "pr1_edio_data_in7", "eQEP2_strobe", "pr1_edio_data_out7", "pr1_pru1_pru_r30_7", "pr1_pru1_pru_r31_7", "gpio2_13"),
+ _PIN(0x8c0, "LCD_DATA8", 76, 7, "lcd_data8", "gpmc_a12", "ehrpwm1_tripzone_input", "mcasp0_aclkx", "uart5_txd", "pr1_mii0_rxd3", "uart2_ctsn", "gpio2_14"),
+ _PIN(0x8c4, "LCD_DATA9", 76, 7, "lcd_data9", "gpmc_a13", "ehrpwm0_synco", "mcasp0_fsx", "uart5_rxd", "pr1_mii0_rxd2", "uart2_rtsn", "gpio2_15"),
+ _PIN(0x8c8, "LCD_DATA10", 77, 7, "lcd_data10", "gpmc_a14", "ehrpwm1A", "mcasp0_axr0", NULL, "pr1_mii0_rxd1", "uart3_ctsn", "gpio2_16"),
+ _PIN(0x8cc, "LCD_DATA11", 78, 7, "lcd_data11", "gpmc_a15", "ehrpwm1B", "mcasp0_ahclkr", "mcasp0_axr2", "pr1_mii0_rxd0", "uart3_rtsn", "gpio2_17"),
+ _PIN(0x8d0, "LCD_DATA12", 8, 7, "lcd_data12", "gpmc_a16", "eQEP1A_in", "mcasp0_aclkr", "mcasp0_axr2", "pr1_mii0_rxlink", "uart4_ctsn", "gpio0_8"),
+ _PIN(0x8d4, "LCD_DATA13", 9, 7, "lcd_data13", "gpmc_a17", "eQEP1B_in", "mcasp0_fsr", "mcasp0_axr3", "pr1_mii0_rxer", "uart4_rtsn", "gpio0_9"),
+ _PIN(0x8d8, "LCD_DATA14", 10, 7, "lcd_data14", "gpmc_a18", "eQEP1_index", "mcasp0_axr1", "uart5_rxd", "pr1_mii_mr0_clk", "uart5_ctsn", "gpio0_10"),
+ _PIN(0x8dc, "LCD_DATA15", 11, 7, "lcd_data15", "gpmc_a19", "eQEP1_strobe", "mcasp0_ahclkx", "mcasp0_axr3", "pr1_mii0_rxdv", "uart5_rtsn", "gpio0_11"),
+ _PIN(0x8e0, "LCD_VSYNC", 86, 7, "lcd_vsync", "gpmc_a8", "gpmc_a1", "pr1_edio_data_in2", "pr1_edio_data_out2", "pr1_pru1_pru_r30_8", "pr1_pru1_pru_r31_8", "gpio2_22"),
+ _PIN(0x8e4, "LCD_HSYNC", 87, 7, "lcd_hsync", "gmpc_a9", "gpmc_a2", "pr1_edio_data_in3", "pr1_edio_data_out3", "pr1_pru1_pru_r30_9", "pr1_pru1_pru_r31_9", "gpio2_23"),
+ _PIN(0x8e8, "LCD_PCLK", 88, 7, "lcd_pclk", "gpmc_a10", "pr1_mii0_crs", "pr1_edio_data_in4", "pr1_edio_data_out4", "pr1_pru1_pru_r30_10", "pr1_pru1_pru_r31_10", "gpio2_24"),
+ _PIN(0x8ec, "LCD_AC_BIAS_EN", 89, 7, "lcd_ac_bias_en", "gpmc_a11", "pr1_mii1_crs", "pr1_edio_data_in5", "pr1_edio_data_out5", "pr1_pru1_pru_r30_11", "pr1_pru1_pru_r31_11", "gpio2_25"),
+ _PIN(0x8f0, "MMC0_DAT3", 90, 7, "mmc0_dat3", "gpmc_a20", "uart4_ctsn", "timer5", "uart1_dcdn", "pr1_pru0_pru_r30_8", "pr1_pru0_pru_r31_8", "gpio2_26"),
+ _PIN(0x8f4, "MMC0_DAT2", 91, 7, "mmc0_dat2", "gpmc_a21", "uart4_rtsn", "timer6", "uart1_dsrn", "pr1_pru0_pru_r30_9", "pr1_pru0_pru_r31_9", "gpio2_27"),
+ _PIN(0x8f8, "MMC0_DAT1", 92, 7, "mmc0_dat1", "gpmc_a22", "uart5_ctsn", "uart3_rxd", "uart1_dtrn", "pr1_pru0_pru_r30_10", "pr1_pru0_pru_r31_10", "gpio2_28"),
+ _PIN(0x8fc, "MMC0_DAT0", 93, 7, "mmc0_dat0", "gpmc_a23", "uart5_rtsn", "uart3_txd", "uart1_rin", "pr1_pru0_pru_r30_11", "pr1_pru0_pru_r31_11", "gpio2_29"),
+ _PIN(0x900, "MMC0_CLK", 94, 7, "mmc0_clk", "gpmc_a24", "uart3_ctsn", "uart2_rxd", "dcan1_tx", "pr1_pru0_pru_r30_12", "pr1_pru0_pru_r31_12", "gpio2_30"),
+ _PIN(0x904, "MMC0_CMD", 95, 7, "mmc0_cmd", "gpmc_a25", "uart3_rtsn", "uart2_txd", "dcan1_rx", "pr1_pru0_pru_r30_13", "pr1_pru0_pru_r31_13", "gpio2_31"),
+ _PIN(0x908, "MII1_COL", 96, 7, "gmii1_col", "rmii2_refclk", "spi1_sclk", "uart5_rxd", "mcasp1_axr2", "mmc2_dat3", "mcasp0_axr2", "gpio3_0"),
+ _PIN(0x90c, "MII1_CRS", 97, 7, "gmii1_crs", "rmii1_crs_dv", "spi1_d0", "I2C1_SDA", "mcasp1_aclkx", "uart5_ctsn", "uart2_rxd", "gpio3_1"),
+ _PIN(0x910, "MII1_RX_ER", 98, 7, "gmii1_rxerr", "rmii1_rxerr", "spi1_d1", "I2C1_SCL", "mcasp1_fsx", "uart5_rtsn", "uart2_txd", "gpio3_2"),
+ _PIN(0x914, "MII1_TX_EN", 99, 7, "gmii1_txen", "rmii1_txen", "rgmii1_tctl", "timer4", "mcasp1_axr0", "eQEP0_index", "mmc2_cmd", "gpio3_3"),
+ _PIN(0x918, "MII1_RX_DV", 100, 7, "gmii1_rxdv", "cd_memory_clk", "rgmii1_rctl", "uart5_txd", "mcasp1_aclkx", "mmc2_dat0", "mcasp0_aclkr", "gpio3_4"),
+ _PIN(0x91c, "MII1_TXD3", 16, 7, "gmii1_txd3", "dcan0_tx", "rgmii1_td3", "uart4_rxd", "mcasp1_fsx", "mmc2_dat1", "mcasp0_fsr", "gpio0_16"),
+ _PIN(0x920, "MII1_TXD2", 17, 7, "gmii1_txd2", "dcan0_rx", "rgmii1_td2", "uart4_txd", "mcasp1_axr0", "mmc2_dat2", "mcasp0_ahclkx", "gpio0_17"),
+ _PIN(0x924, "MII1_TXD1", 21, 7, "gmii1_txd1", "rmii1_txd1", "rgmii1_td1", "mcasp1_fsr", "mcasp1_axr1", "eQEP0A_in", "mmc1_cmd", "gpio0_21"),
+ _PIN(0x928, "MII1_TXD0", 28, 7, "gmii1_txd0", "rmii1_txd0", "rgmii1_td0", "mcasp1_axr2", "mcasp1_aclkr", "eQEP0B_in", "mmc1_clk", "gpio0_28"),
+ _PIN(0x92c, "MII1_TX_CLK", 105, 7, "gmii1_txclk", "uart2_rxd", "rgmii1_tclk", "mmc0_dat7", "mmc1_dat0", "uart1_dcdn", "mcasp0_aclkx", "gpio3_9"),
+ _PIN(0x930, "MII1_RX_CLK", 106, 7, "gmii1_rxclk", "uart2_txd", "rgmii1_rclk", "mmc0_dat6", "mmc1_dat1", "uart1_dsrn", "mcasp0_fsx", "gpio3_10"),
+ _PIN(0x934, "MII1_RXD3", 82, 7, "gmii1_rxd3", "uart3_rxd", "rgmii1_rd3", "mmc0_dat5", "mmc1_dat2", "uart1_dtrn", "mcasp0_axr0", "gpio2_18"),
+ _PIN(0x938, "MII1_RXD2", 83, 7, "gmii1_rxd2", "uart3_txd", "rgmii1_rd2", "mmc0_dat4", "mmc1_dat3", "uart1_rin", "mcasp0_axr1", "gpio2_19"),
+ _PIN(0x93c, "MII1_RXD1", 84, 7, "gmii1_rxd1", "rmii1_rxd1", "rgmii1_rd1", "mcasp1_axr3", "mcasp1_fsr", "eQEP0_strobe", "mmc2_clk", "gpio2_20"),
+ _PIN(0x940, "MII1_RXD0", 85, 7, "gmii1_rxd0", "rmii1_rxd0", "rgmii1_rd0", "mcasp1_ahclkx", "mcasp1_ahclkr", "mcasp1_aclkr", "mcasp0_axr3", "gpio2_21"),
+ _PIN(0x944, "RMII1_REF_CLK", 29, 7, "rmii1_refclk", "xdma_event_intr2", "spi1_cs0", "uart5_txd", "mcasp1_axr3", "mmc0_pow", "mcasp1_ahclkx", "gpio0_29"),
+ _PIN(0x948, "MDIO", 0, 7, "mdio_data", "timer6", "uart5_rxd", "uart3_ctsn", "mmc0_sdcd","mmc1_cmd", "mmc2_cmd","gpio0_0"),
+ _PIN(0x94c, "MDC", 1, 7, "mdio_clk", "timer5", "uart5_txd", "uart3_rtsn", "mmc0_sdwp", "mmc1_clk", "mmc2_clk", "gpio0_1"),
+ _PIN(0x950, "SPI0_SCLK", 2, 7, "spi0_sclk", "uart2_rxd", "I2C2_SDA", "ehrpwm0A", "pr1_uart0_cts_n", "pr1_edio_sof", "EMU2", "gpio0_2"),
+ _PIN(0x954, "SPI0_D0", 3, 7, "spi0_d0", "uart2_txd", "I2C2_SCL", "ehrpwm0B", "pr1_uart0_rts_n", "pr1_edio_latch_in", "EMU3", "gpio0_3"),
+ _PIN(0x958, "SPIO_D1", 4, 7, "spi0_d1", "mmc1_sdwp", "I2C1_SDA", "ehrpwm0_tripzone_input", "pr1_uart0_rxd", "pr1_edio_data_in0", "pr1_edio_data_out0", "gpio0_4"),
+ _PIN(0x95c, "SPI0_CS0", 5, 7, "spi0_cs0", "mmc2_sdwp", "I2C1_SCL", "ehrpwm0_synci", "pr1_uart0_txd", "pr1_edio_data_in1", "pr1_edio_data_out1", "gpio0_5"),
+ _PIN(0x960, "SPI0_CS1", 6, 7, "spi0_cs1", "uart3_rxd", "eCAP1_in_PWM1_out", "mcc0_pow", "xdm_event_intr2", "mmc0_sdcd", "EMU4", "gpio0_6"),
+ _PIN(0x964, "ECAP0_IN_PWM0_OUT",7, 7, "eCAP0_in_PWM0_out", "uart3_txd", "spi1_cs1", "pr1_ecap0_ecap_capin_apwm_o", "spi1_sclk", "mmc0_sdwp", "xdma_event_intr2", "gpio0_7"),
+ _PIN(0x968, "UART0_CTSn", 40, 7, "uart0_ctsn", "uart4_rxd", "dcan1_tx", "I2C1_SDA", "spi1_d0", "timer7", "pr1_edc_sync0_out", "gpio1_8"),
+ _PIN(0x96c, "UART0_RTSn", 41, 7, "uart0_rtsn", "uart4_txd", "dcan1_rx", "I2C1_SCL", "spi1_d1", "spi1_cs0", "pr1_edc_sync1_out", "gpio1_9"),
+ _PIN(0x970, "UART0_rxd", 42, 7, "uart0_rxd", "spi1_cs0", "dcan0_tx", "I2C2_SDA", "eCAP2_in_PWM2_out", "pr1_pru1_pru_r30_14", "pr1_pru1_pru_r31_14", "gpio1_10"),
+ _PIN(0x974, "UART0_txd", 43, 7, "uart0_txd", "spi1_cs1", "dcan0_rx", "I2C2_SCL", "eCAP1_in_PWM1_out", "pr1_pru1_pru_r30_15", "pr1_pru1_pru_r31_15", "gpio1_11"),
+ _PIN(0x978, "UART1_CTSn", 12, 7, "uart1_ctsn", "timer6_mux1", "dcan0_tx", "I2C2_SDA", "spi1_cs0", "pr1_uart0_cts_n", "pr1_edc_latch0_in", "gpio0_12"),
+ _PIN(0x97c, "UART1_RTSn", 13, 7, "uart1_rtsn", "timer5_mux1", "dcan0_rx", "I2C2_SCL", "spi1_cs1", "pr1_uart0_rts_n ", "pr1_edc_latch1_in", "gpio0_13"),
+ _PIN(0x980, "UART1_RXD", 14, 7, "uart1_rxd", "mmc1_sdwp", "dcan1_tx", "I2C1_SDA", NULL, "pr1_uart0_rxd", "pr1_pru1_pru_r31_16", "gpio0_14"),
+ _PIN(0x984, "UART1_TXD", 15, 7, "uart1_txd", "mmc2_sdwp", "dcan1_rx", "I2C1_SCL", NULL, "pr1_uart0_txd", "pr1_pru0_pru_r31_16", "gpio0_15"),
+ _PIN(0x988, "I2C0_SDA", 101, 7, "I2C0_SDA", "timer4", "uart2_ctsn", "eCAP2_in_PWM2_out", NULL, NULL, NULL, "gpio3_5"),
+ _PIN(0x98c, "I2C0_SCL", 102, 7, "I2C0_SCL", "timer7", "uart2_rtsn", "eCAP1_in_PWM1_out", NULL, NULL, NULL, "gpio3_6"),
+ _PIN(0x990, "MCASP0_ACLKX", 110, 7, "mcasp0_aclkx", "ehrpwm0A", NULL, "spi1_sclk", "mmc0_sdcd", "pr1_pru0_pru_r30_0", "pr1_pru0_pru_r31_0", "gpio3_14"),
+ _PIN(0x994, "MCASP0_FSX", 111, 7, "mcasp0_fsx", "ehrpwm0B", NULL, "spi1_d0", "mmc1_sdcd", "pr1_pru0_pru_r30_1", "pr1_pru0_pru_r31_1", "gpio3_15"),
+ _PIN(0x998, "MCASP0_AXR0", 112, 7, "mcasp0_axr0", "ehrpwm0_tripzone_input", NULL, "spi1_d1", "mmc2_sdcd", "pr1_pru0_pru_r30_2", "pr1_pru0_pru_r31_2", "gpio3_16"),
+ _PIN(0x99c, "MCASP0_AHCLKR", 113, 7, "mcasp0_ahclkr", "ehrpwm0_synci", "mcasp0_axr2", "spi1_cs0", "eCAP2_in_PWM2_out", "pr1_pru0_pru_r30_3", "pr1_pru0_pru_r31_3", "gpio3_17"),
+ _PIN(0x9a0, "MCASP0_ACLKR", 114, 7, "mcasp0_aclkr", "eQEP0A_in", "mcasp0_axr2", "mcasp1_aclkx", "mmc0_sdwp", "pr1_pru0_pru_r30_4", "pr1_pru0_pru_r31_4", "gpio3_18"),
+ _PIN(0x9a4, "MCASP0_FSR", 115, 7, "mcasp0_fsr", "eQEP0B_in", "mcasp0_axr3", "mcasp1_fsx", "EMU2", "pr1_pru0_pru_r30_5", "pr1_pru0_pru_r31_5", "gpio3_19"),
+ _PIN(0x9a8, "MCASP0_AXR1", 116, 7, "mcasp0_axr1", "eQEP0_index", NULL, "mcasp1_axr0", "EMU3", "pr1_pru0_pru_r30_6", "pr1_pru0_pru_r31_6", "gpio3_20"),
+ _PIN(0x9ac, "MCASP0_AHCLKX", 117, 7, "mcasp0_ahclkx", "eQEP0_strobe", "mcasp0_axr3", "mcasp1_axr1", "EMU4", "pr1_pru0_pru_r30_7", "pr1_pru0_pru_r31_7", "gpio3_21"),
+ _PIN(0x9b0, "XDMA_EVENT_INTR0", 19, 7, "xdma_event_intr0", NULL, "timer4", "clkout1", "spi1_cs1", "pr1_pru1_pru_r31_16", "EMU2", "gpio0_19"),
+ _PIN(0x9b4, "XDMA_EVENT_INTR1", 20, 7, "xdma_event_intr1", NULL, "tclkin", "clkout2", "timer7", "pr1_pru0_pru_r31_16", "EMU3", "gpio0_20"),
+#if 0
+ _PIN(0x9b8, "nresetin_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9bc, "porz", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9c0, "nnmi", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9c4, "osc0_in", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9c8, "osc0_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9cc, "osc0_vss", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9d0, "tms", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9d4, "tdi", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9d8, "tdo", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9dc, "tck", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9e0, "ntrst", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+#endif
+ _PIN(0x9e4, "EMU0", 103, 7, "EMU0", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_7"),
+ _PIN(0x9e8, "EMU1", 104, 0, "EMU1", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_8"),
+#if 0
+ _PIN(0x9ec, "osc1_in", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9f0, "osc1_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9f4, "osc1_vss", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9f8, "rtc_porz", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0x9fc, "pmic_power_en", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa00, "ext_wakeup", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa04, "enz_kaldo_1p8v", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+#endif
+ _PIN(0xa08, "USB0_DM", 0, 0, "USB0_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa0c, "USB0_DP", 0, 0, "USB0_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa10, "USB0_CE", 0, 0, "USB0_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa14, "USB0_ID", 0, 0, "USB0_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa18, "USB0_VBUS", 0, 0, "USB0_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa1c, "USB0_DRVVBUS", 18, 7, "USB0_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio0_18"),
+ _PIN(0xa20, "USB1_DM", 0, 0, "USB1_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa24, "USB1_DP", 0, 0, "USB1_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa28, "USB1_CE", 0, 0, "USB1_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa2c, "USB1_ID", 0, 0, "USB1_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa30, "USB1_VBUS", 0, 0, "USB1_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa34, "USB1_DRVVBUS", 109, 7, "USB1_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_13"),
+#if 0
+ _PIN(0xa38, "ddr_resetn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa3c, "ddr_csn0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa40, "ddr_cke", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa44, "ddr_ck", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa48, "ddr_nck", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa4c, "ddr_casn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa50, "ddr_rasn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa54, "ddr_wen", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa58, "ddr_ba0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa5c, "ddr_ba1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa60, "ddr_ba2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa64, "ddr_a0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa68, "ddr_a1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa6c, "ddr_a2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa70, "ddr_a3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa74, "ddr_a4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa78, "ddr_a5", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa7c, "ddr_a6", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa80, "ddr_a7", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa84, "ddr_a8", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa88, "ddr_a9", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa8c, "ddr_a10", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa90, "ddr_a11", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa94, "ddr_a12", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa98, "ddr_a13", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa9c, "ddr_a14", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaa0, "ddr_a15", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaa4, "ddr_odt", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaa8, "ddr_d0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaac, "ddr_d1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xab0, "ddr_d2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xab4, "ddr_d3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xab8, "ddr_d4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xabc, "ddr_d5", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xac0, "ddr_d6", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xac4, "ddr_d7", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xac8, "ddr_d8", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xacc, "ddr_d9", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xad0, "ddr_d10", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xad4, "ddr_d11", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xad8, "ddr_d12", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xadc, "ddr_d13", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xae0, "ddr_d14", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xae4, "ddr_d15", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xae8, "ddr_dqm0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaec, "ddr_dqm1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaf0, "ddr_dqs0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaf4, "ddr_dqsn0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xaf8, "ddr_dqs1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xafc, "ddr_dqsn1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb00, "ddr_vref", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb04, "ddr_vtp", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb08, "ddr_strben0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb0c, "ddr_strben1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb2c, "ain0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb28, "ain1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb24, "ain2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb20, "ain3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb1c, "ain4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb18, "ain5", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb14, "ain6", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb10, "ain7", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb30, "vrefp", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb34, "vrefn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb38, "avdd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb3c, "avss", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb40, "iforce", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb44, "vsense", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xb48, "testout", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+#endif
+ { .ballname = NULL },
+};
+
+const struct sitara_cm_device sitara_cm_dev = {
+ .padconf_muxmode_mask = 0x7,
+ .padconf_sate_mask = 0x78,
+ .padstate = (struct sitara_cm_padstate *) &ti_padstate_devmap,
+ .padconf = (struct sitara_cm_padconf *) &ti_padconf_devmap,
+};
+
+int
+sitara_cm_padconf_set_gpioflags(uint32_t gpio, uint32_t flags)
+{
+ unsigned int state = 0;
+ if (flags & GPIO_PIN_OUTPUT) {
+ if (flags & GPIO_PIN_PULLUP)
+ state = PADCONF_OUTPUT_PULLUP;
+ else
+ state = PADCONF_OUTPUT;
+ } else if (flags & GPIO_PIN_INPUT) {
+ if (flags & GPIO_PIN_PULLUP)
+ state = PADCONF_INPUT_PULLUP;
+ else if (flags & GPIO_PIN_PULLDOWN)
+ state = PADCONF_INPUT_PULLDOWN;
+ else
+ state = PADCONF_INPUT;
+ }
+ return sitara_cm_padconf_set_gpiomode(gpio, state);
+}
+
+void
+sitara_cm_padconf_get_gpioflags(uint32_t gpio, uint32_t *flags)
+{
+ unsigned int state;
+ if (sitara_cm_padconf_get_gpiomode(gpio, &state) != 0)
+ *flags = 0;
+ else {
+ switch (state) {
+ case PADCONF_OUTPUT:
+ *flags = GPIO_PIN_OUTPUT;
+ break;
+ case PADCONF_OUTPUT_PULLUP:
+ *flags = GPIO_PIN_OUTPUT | GPIO_PIN_PULLUP;
+ break;
+ case PADCONF_INPUT:
+ *flags = GPIO_PIN_INPUT;
+ break;
+ case PADCONF_INPUT_PULLUP:
+ *flags = GPIO_PIN_INPUT | GPIO_PIN_PULLUP;
+ break;
+ case PADCONF_INPUT_PULLDOWN:
+ *flags = GPIO_PIN_INPUT | GPIO_PIN_PULLDOWN;
+ break;
+ default:
+ *flags = 0;
+ break;
+ }
+ }
+}
--- /dev/null
+/* $OpenBSD: am335x_prcmreg.h,v 1.4 2014/03/18 07:34:17 syl Exp $ */
+/*
+ * Copyright (c) 2013 Raphael Graf <r@undefined.ch>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define AM335X_CLKCTRL_MODULEMODE_ENABLE 2
+#define AM335X_CLKCTRL_MODULEMODE_DISABLE 0
+#define AM335X_CLKCTRL_MODULEMODE_MASK 0x00000003
+
+#define PRCM_AM335X_CM_PER 0x0000
+#define PRCM_AM335X_USB0_CLKCTRL 0x001c
+#define PRCM_AM335X_TPTC0_CLKCTRL 0x0024
+#define PRCM_AM335X_MMC0_CLKCTRL 0x003c
+#define PRCM_AM335X_I2C2_CLKCTRL 0x0044
+#define PRCM_AM335X_I2C1_CLKCTRL 0x0048
+#define PRCM_AM335X_TIMER2_CLKCTRL 0x0080
+#define PRCM_AM335X_TIMER3_CLKCTRL 0x0084
+#define PRCM_AM335X_GPIO1_CLKCTRL 0x00ac
+#define PRCM_AM335X_GPIO2_CLKCTRL 0x00b0
+#define PRCM_AM335X_GPIO3_CLKCTRL 0x00b4
+#define PRCM_AM335X_TPCC_CLKCTRL 0x00bc
+#define PRCM_AM335X_MMC1_CLKCTRL 0x00f4
+#define PRCM_AM335X_MMC2_CLKCTRL 0x00f8
+#define PRCM_AM335X_TPTC1_CLKCTRL 0x00fc
+#define PRCM_AM335X_TPTC2_CLKCTRL 0x0100
+#define PRCM_AM335X_CM_WKUP 0x0400
+#define PRCM_AM335X_GPIO0_CLKCTRL 0x0408
+#define PRCM_AM335X_TIMER0_CLKCTRL 0x0410
+#define PRCM_AM335X_I2C0_CLKCTRL 0x04b8
+#define PRCM_AM335X_CM_DPLL 0x0500
+#define PRCM_AM335X_CLKSEL_TIMER2_CLK 0x0508
+#define PRCM_AM335X_CLKSEL_TIMER3_CLK 0x050c
+#define PRCM_AM335X_CM_MPU 0x0600
+#define PRCM_AM335X_CM_DEVICE 0x0700
+#define PRCM_AM335X_CM_RTC 0x0800
+#define PRCM_AM335X_CM_GFX 0x0900
+#define PRCM_AM335X_CM_CEFUSE 0x0a00
+#define PRCM_AM335X_PRM_IRQ 0x0b00
+#define PRCM_AM335X_PRM_PER 0x0c00
+#define PRCM_AM335X_PRM_WKUP 0x0d00
+#define PRCM_AM335X_PRM_MPU 0x0e00
+#define PRCM_AM335X_PRM_DEVICE 0x0f00
+#define PRCM_AM335X_PRM_RTC 0x1000
+#define PRCM_AM335X_PRM_GFX 0x1100
+#define PRCM_AM335X_PRM_CEFUSE 0x1200
--- /dev/null
+/* $OpenBSD: dmtimer.c,v 1.6 2015/01/22 14:33:01 krw Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ * Copyright (c) 2013 Raphael Graf <r@undefined.ch>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * WARNING - this timer initializion has not been checked
+ * to see if it will do _ANYTHING_ sane if the omap enters
+ * low power mode.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+#include <sys/evcount.h>
+#include <sys/device.h>
+#include <sys/timetc.h>
+#include <dev/clock_subr.h>
+#include <machine/bus.h>
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/prcmvar.h>
+
+#include <machine/intr.h>
+#include <arm/cpufunc.h>
+
+/* registers */
+#define DM_TIDR 0x000
+#define DM_TIDR_MAJOR 0x00000700
+#define DM_TIDR_MINOR 0x0000003f
+#define DM_TIOCP_CFG 0x010
+#define DM_TIOCP_CFG_IDLEMODE (3<<2)
+#define DM_TIOCP_CFG_EMUFREE (1<<1)
+#define DM_TIOCP_CFG_SOFTRESET (1<<0)
+#define DM_TISR 0x028
+#define DM_TISR_TCAR (1<<2)
+#define DM_TISR_OVF (1<<1)
+#define DM_TISR_MAT (1<<0)
+#define DM_TIER 0x2c
+#define DM_TIER_TCAR_EN (1<<2)
+#define DM_TIER_OVF_EN (1<<1)
+#define DM_TIER_MAT_EN (1<<0)
+#define DM_TIECR 0x30
+#define DM_TIECR_TCAR_EN (1<<2)
+#define DM_TIECR_OVF_EN (1<<1)
+#define DM_TIECR_MAT_EN (1<<0)
+#define DM_TWER 0x034
+#define DM_TWER_TCAR_EN (1<<2)
+#define DM_TWER_OVF_EN (1<<1)
+#define DM_TWER_MAT_EN (1<<0)
+#define DM_TCLR 0x038
+#define DM_TCLR_GPO (1<<14)
+#define DM_TCLR_CAPT (1<<13)
+#define DM_TCLR_PT (1<<12)
+#define DM_TCLR_TRG (3<<10)
+#define DM_TCLR_TRG_O (1<<10)
+#define DM_TCLR_TRG_OM (2<<10)
+#define DM_TCLR_TCM (3<<8)
+#define DM_TCLR_TCM_RISE (1<<8)
+#define DM_TCLR_TCM_FALL (2<<8)
+#define DM_TCLR_TCM_BOTH (3<<8)
+#define DM_TCLR_SCPWM (1<<7)
+#define DM_TCLR_CE (1<<6)
+#define DM_TCLR_PRE (1<<5)
+#define DM_TCLR_PTV (7<<2)
+#define DM_TCLR_AR (1<<1)
+#define DM_TCLR_ST (1<<0)
+#define DM_TCRR 0x03c
+#define DM_TLDR 0x040
+#define DM_TTGR 0x044
+#define DM_TWPS 0x048
+#define DM_TWPS_TMAR (1<<4)
+#define DM_TWPS_TTGR (1<<3)
+#define DM_TWPS_TLDR (1<<2)
+#define DM_TWPS_TCLR (1<<0)
+#define DM_TWPS_TCRR (1<<1)
+#define DM_TWPS_ALL 0x1f
+#define DM_TMAR 0x04c
+#define DM_TCAR 0x050
+#define DM_TSICR 0x054
+#define DM_TSICR_POSTED (1<<2)
+#define DM_TSICR_SFT (1<<1)
+#define DM_TCAR2 0x058
+
+#define TIMER_FREQUENCY 32768 /* 32kHz is used, selectable */
+#define MAX_TIMERS 2
+
+static struct evcount clk_count;
+static struct evcount stat_count;
+
+void dmtimer_attach(struct device *parent, struct device *self, void *args);
+int dmtimer_intr(void *frame);
+void dmtimer_wait(int reg);
+void dmtimer_cpu_initclocks(void);
+void dmtimer_delay(u_int);
+void dmtimer_setstatclockrate(int newhz);
+
+u_int dmtimer_get_timecount(struct timecounter *);
+
+static struct timecounter dmtimer_timecounter = {
+ dmtimer_get_timecount, NULL, 0xffffffff, 0, "dmtimer", 0, NULL
+};
+
+bus_space_handle_t dmtimer_ioh0;
+int dmtimer_irq = 0;
+
+struct dmtimer_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh[MAX_TIMERS];
+ u_int32_t sc_irq;
+ u_int32_t sc_ticks_per_second;
+ u_int32_t sc_ticks_per_intr;
+ u_int32_t sc_ticks_err_cnt;
+ u_int32_t sc_ticks_err_sum;
+ u_int32_t sc_statvar;
+ u_int32_t sc_statmin;
+ u_int32_t sc_nexttickevent;
+ u_int32_t sc_nextstatevent;
+};
+
+struct cfattach dmtimer_ca = {
+ sizeof (struct dmtimer_softc), NULL, dmtimer_attach
+};
+
+struct cfdriver dmtimer_cd = {
+ NULL, "dmtimer", DV_DULL
+};
+
+void
+dmtimer_attach(struct device *parent, struct device *self, void *args)
+{
+ struct dmtimer_softc *sc = (struct dmtimer_softc *)self;
+ struct armv7_attach_args *aa = args;
+ bus_space_handle_t ioh;
+ u_int32_t rev, cfg;
+
+ sc->sc_iot = aa->aa_iot;
+
+ if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &ioh))
+ panic("%s: bus_space_map failed!\n", __func__);
+
+
+ prcm_setclock(1, PRCM_CLK_SPEED_32);
+ prcm_setclock(2, PRCM_CLK_SPEED_32);
+ prcm_enablemodule(PRCM_TIMER2);
+ prcm_enablemodule(PRCM_TIMER3);
+
+ /* reset */
+ bus_space_write_4(sc->sc_iot, ioh, DM_TIOCP_CFG,
+ DM_TIOCP_CFG_SOFTRESET);
+ while (bus_space_read_4(sc->sc_iot, ioh, DM_TIOCP_CFG)
+ & DM_TIOCP_CFG_SOFTRESET)
+ ;
+
+ if (self->dv_unit == 0) {
+ dmtimer_ioh0 = ioh;
+ dmtimer_irq = aa->aa_dev->irq[0];
+ /* enable write posted mode */
+ bus_space_write_4(sc->sc_iot, ioh, DM_TSICR, DM_TSICR_POSTED);
+ /* stop timer */
+ bus_space_write_4(sc->sc_iot, ioh, DM_TCLR, 0);
+ } else if (self->dv_unit == 1) {
+ /* start timer because it is used in delay */
+ /* interrupts and posted mode are disabled */
+ sc->sc_irq = dmtimer_irq;
+ sc->sc_ioh[0] = dmtimer_ioh0;
+ sc->sc_ioh[1] = ioh;
+
+ bus_space_write_4(sc->sc_iot, ioh, DM_TCRR, 0);
+ bus_space_write_4(sc->sc_iot, ioh, DM_TLDR, 0);
+ bus_space_write_4(sc->sc_iot, ioh, DM_TCLR,
+ DM_TCLR_AR | DM_TCLR_ST);
+
+ dmtimer_timecounter.tc_frequency = TIMER_FREQUENCY;
+ dmtimer_timecounter.tc_priv = sc;
+ tc_init(&dmtimer_timecounter);
+ arm_clock_register(dmtimer_cpu_initclocks, dmtimer_delay,
+ dmtimer_setstatclockrate, NULL);
+ }
+ else
+ panic("attaching too many dmtimers at 0x%lx",
+ aa->aa_dev->mem[0].addr);
+
+ /* set IDLEMODE to smart-idle */
+ cfg = bus_space_read_4(sc->sc_iot, ioh, DM_TIOCP_CFG);
+ bus_space_write_4(sc->sc_iot, ioh, DM_TIOCP_CFG,
+ (cfg & ~DM_TIOCP_CFG_IDLEMODE) | 0x02);
+
+ rev = bus_space_read_4(sc->sc_iot, ioh, DM_TIDR);
+ printf(" rev %d.%d\n", (rev & DM_TIDR_MAJOR) >> 8, rev & DM_TIDR_MINOR);
+}
+
+/*
+ * See comment in arm/xscale/i80321_clock.c
+ *
+ * Counter is count up, but with autoreload timers it is not possible
+ * to detect how many interrupts passed while interrupts were blocked.
+ * Also it is not possible to atomically add to the register.
+ *
+ * To work around this two timers are used, one is used as a reference
+ * clock without reload, however we just disable the interrupt it
+ * could generate.
+ *
+ * Internally this keeps track of when the next timer should fire
+ * and based on that time and the current value of the reference
+ * clock a number is written into the timer count register to schedule
+ * the next event.
+ */
+
+int
+dmtimer_intr(void *frame)
+{
+ struct dmtimer_softc *sc = dmtimer_cd.cd_devs[1];
+ u_int32_t now, r, nextevent;
+ int32_t duration;
+
+ now = bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
+
+ while ((int32_t) (sc->sc_nexttickevent - now) <= 0) {
+ sc->sc_nexttickevent += sc->sc_ticks_per_intr;
+ sc->sc_ticks_err_sum += sc->sc_ticks_err_cnt;
+
+ while (sc->sc_ticks_err_sum > hz) {
+ sc->sc_nexttickevent += 1;
+ sc->sc_ticks_err_sum -= hz;
+ }
+
+ clk_count.ec_count++;
+ hardclock(frame);
+ }
+
+ while ((int32_t) (sc->sc_nextstatevent - now) <= 0) {
+ do {
+ r = random() & (sc->sc_statvar - 1);
+ } while (r == 0); /* random == 0 not allowed */
+ sc->sc_nextstatevent += sc->sc_statmin + r;
+ stat_count.ec_count++;
+ statclock(frame);
+ }
+ if ((sc->sc_nexttickevent - now) < (sc->sc_nextstatevent - now))
+ nextevent = sc->sc_nexttickevent;
+ else
+ nextevent = sc->sc_nextstatevent;
+
+ duration = nextevent -
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
+
+ if (duration <= 0)
+ duration = 1; /* trigger immediately. */
+
+ if (duration > sc->sc_ticks_per_intr + 1) {
+ printf("%s: time lost!\n", __func__);
+ /*
+ * If interrupts are blocked too long, like during
+ * the root prompt or ddb, the timer can roll over,
+ * this will allow the system to continue to run
+ * even if time is lost.
+ */
+ duration = sc->sc_ticks_per_intr;
+ sc->sc_nexttickevent = now;
+ sc->sc_nextstatevent = now;
+ }
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TISR,
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh[0], DM_TISR));
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCRR, -duration);
+ dmtimer_wait(DM_TWPS_ALL);
+
+ return 1;
+}
+
+/*
+ * would be interesting to play with trigger mode while having one timer
+ * in 32KHz mode, and the other timer running in sysclk mode and use
+ * the high resolution speeds (matters more for delay than tick timer
+ */
+
+void
+dmtimer_cpu_initclocks()
+{
+ struct dmtimer_softc *sc = dmtimer_cd.cd_devs[1];
+
+ stathz = 128;
+ profhz = 1024;
+
+ sc->sc_ticks_per_second = TIMER_FREQUENCY; /* 32768 */
+
+ setstatclockrate(stathz);
+
+ sc->sc_ticks_per_intr = sc->sc_ticks_per_second / hz;
+ sc->sc_ticks_err_cnt = sc->sc_ticks_per_second % hz;
+ sc->sc_ticks_err_sum = 0;
+
+ /* establish interrupts */
+ arm_intr_establish(sc->sc_irq, IPL_CLOCK, dmtimer_intr,
+ NULL, "tick");
+
+ /* setup timer 0 */
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TLDR, 0);
+
+ sc->sc_nexttickevent = sc->sc_nextstatevent = bus_space_read_4(sc->sc_iot,
+ sc->sc_ioh[1], DM_TCRR) + sc->sc_ticks_per_intr;
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TIER, DM_TIER_OVF_EN);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TWER, DM_TWER_OVF_EN);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TISR, /*clear interrupt flags */
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh[0], DM_TISR));
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCRR, -sc->sc_ticks_per_intr);
+ dmtimer_wait(DM_TWPS_ALL);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCLR, /* autoreload and start */
+ DM_TCLR_AR | DM_TCLR_ST);
+ dmtimer_wait(DM_TWPS_ALL);
+}
+
+void
+dmtimer_wait(int reg)
+{
+ struct dmtimer_softc *sc = dmtimer_cd.cd_devs[1];
+ while (bus_space_read_4(sc->sc_iot, sc->sc_ioh[0], DM_TWPS) & reg)
+ ;
+}
+
+void
+dmtimer_delay(u_int usecs)
+{
+ struct dmtimer_softc *sc = dmtimer_cd.cd_devs[1];
+ u_int32_t clock, oclock, delta, delaycnt;
+ volatile int j;
+ int csec, usec;
+
+ if (usecs > (0x80000000 / (TIMER_FREQUENCY))) {
+ csec = usecs / 10000;
+ usec = usecs % 10000;
+
+ delaycnt = (TIMER_FREQUENCY / 100) * csec +
+ (TIMER_FREQUENCY / 100) * usec / 10000;
+ } else {
+ delaycnt = TIMER_FREQUENCY * usecs / 1000000;
+ }
+ if (delaycnt <= 1)
+ for (j = 100; j > 0; j--)
+ ;
+
+ if (sc->sc_ioh[1] == 0) {
+ /* BAH */
+ for (; usecs > 0; usecs--)
+ for (j = 100; j > 0; j--)
+ ;
+ return;
+ }
+ oclock = bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
+ while (1) {
+ for (j = 100; j > 0; j--)
+ ;
+ clock = bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
+ delta = clock - oclock;
+ if (delta > delaycnt)
+ break;
+ }
+
+}
+
+void
+dmtimer_setstatclockrate(int newhz)
+{
+ struct dmtimer_softc *sc = dmtimer_cd.cd_devs[1];
+ int minint, statint;
+ int s;
+
+ s = splclock();
+
+ statint = sc->sc_ticks_per_second / newhz;
+ /* calculate largest 2^n which is smaller than just over half statint */
+ sc->sc_statvar = 0x40000000; /* really big power of two */
+ minint = statint / 2 + 100;
+ while (sc->sc_statvar > minint)
+ sc->sc_statvar >>= 1;
+
+ sc->sc_statmin = statint - (sc->sc_statvar >> 1);
+
+ splx(s);
+
+ /*
+ * XXX this allows the next stat timer to occur then it switches
+ * to the new frequency. Rather than switching instantly.
+ */
+}
+
+
+u_int
+dmtimer_get_timecount(struct timecounter *tc)
+{
+ struct dmtimer_softc *sc = dmtimer_timecounter.tc_priv;
+
+ return bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
+}
--- /dev/null
+/* $OpenBSD: edma.c,v 1.5 2015/01/22 14:33:01 krw Exp $ */
+/*
+ * Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/prcmvar.h>
+#include <armv7/omap/edmavar.h>
+
+#define DEVNAME(s) ((s)->sc_dev.dv_xname)
+
+struct edma_softc {
+ struct device sc_dev;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_tpcc;
+
+ void *sc_ih_comp;
+ edma_intr_cb_t sc_intr_cb[64];
+ void *sc_intr_dat[64];
+};
+
+#define EDMA_NUM_DMA_CHANS 64
+#define EDMA_NUM_QDMA_CHANS 8
+#define EDMA_TPCC_DHCM(x) (0x100 + (x * 4))
+#define EDMA_REG_X(x) (0x1000 + (0x200 * x))
+#define EDMA_TPCC_PID 0x0
+#define EDMA_TPCC_EMCR 0x308
+#define EDMA_TPCC_EMCRH 0x30c
+#define EDMA_TPCC_CCERRCLR 0x31c
+#define EDMA_TPCC_DRAE0 0x340
+#define EDMA_TPCC_DRAEH0 0x344
+#define EDMA_TPCC_ESR 0x1010
+#define EDMA_TPCC_ESRH 0x1014
+#define EDMA_TPCC_EESR 0x1030
+#define EDMA_TPCC_EESRH 0x1034
+#define EDMA_TPCC_SECR 0x1040
+#define EDMA_TPCC_SECRH 0x1044
+#define EDMA_TPCC_IER 0x1050
+#define EDMA_TPCC_IERH 0x1054
+#define EDMA_TPCC_IECR 0x1058
+#define EDMA_TPCC_IECRH 0x105c
+#define EDMA_TPCC_IESR 0x1060
+#define EDMA_TPCC_IESRH 0x1064
+#define EDMA_TPCC_IPR 0x1068
+#define EDMA_TPCC_IPRH 0x106c
+#define EDMA_TPCC_ICR 0x1070
+#define EDMA_TPCC_ICRH 0x1074
+#define EDMA_TPCC_IEVAL 0x1078
+#define EDMA_TPCC_OPT(x) (0x4000 + (x * 0x20))
+
+#define TPCC_READ_4(sc, reg) \
+ (bus_space_read_4((sc)->sc_iot, (sc)->sc_tpcc, (reg)))
+#define TPCC_WRITE_4(sc, reg, val) \
+ (bus_space_write_4((sc)->sc_iot, (sc)->sc_tpcc, (reg), (val)))
+#define TPCC_SET(sc, reg, val) \
+ (TPCC_WRITE_4((sc), (reg), (TPCC_READ_4(sc, reg) | (val))))
+#define TPCC_FILTSET(sc, reg, val, filt) \
+ (TPCC_WRITE_4((sc), (reg), (TPCC_READ_4(sc, reg) & (filt)) | (val)))
+
+struct edma_softc *edma_sc;
+
+void edma_attach(struct device *, struct device *, void *);
+int edma_comp_intr(void *);
+
+struct cfattach edma_ca = {
+ sizeof(struct edma_softc), NULL, edma_attach
+};
+
+struct cfdriver edma_cd = {
+ NULL, "edma", DV_DULL
+};
+
+void
+edma_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct armv7_attach_args *aa = aux;
+ struct edma_softc *sc = (struct edma_softc *)self;
+ uint32_t rev;
+ int i;
+
+ sc->sc_iot = aa->aa_iot;
+
+ /* Map Base address for TPCC and TPCTX */
+ if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_tpcc)) {
+ printf("%s: bus_space_map failed for TPCC\n", DEVNAME(sc));
+ return ;
+ }
+
+ /* Enable TPCC and TPTC0 in PRCM */
+ prcm_enablemodule(PRCM_TPCC);
+ prcm_enablemodule(PRCM_TPTC0);
+
+ rev = TPCC_READ_4(sc, EDMA_TPCC_PID);
+ printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
+
+ /* XXX IPL_VM ? */
+ /* Enable interrupts line */
+ sc->sc_ih_comp = arm_intr_establish(aa->aa_dev->irq[0], IPL_VM,
+ edma_comp_intr, sc, DEVNAME(sc));
+ if (sc->sc_ih_comp == NULL) {
+ printf("%s: unable to establish interrupt comp\n", DEVNAME(sc));
+ bus_space_unmap(sc->sc_iot, sc->sc_tpcc,
+ aa->aa_dev->mem[0].size);
+ return ;
+ }
+
+ /* Set global softc */
+ edma_sc = sc;
+
+ /* Clear Event Missed Events */
+ TPCC_WRITE_4(sc, EDMA_TPCC_EMCR, 0xffffffff);
+ TPCC_WRITE_4(sc, EDMA_TPCC_EMCRH, 0xffffffff);
+ TPCC_WRITE_4(sc, EDMA_TPCC_CCERRCLR, 0xffffffff);
+
+ /* Identity Map Channels PaRAM */
+ for (i = 0; i < EDMA_NUM_DMA_CHANS; i++)
+ TPCC_WRITE_4(sc, EDMA_TPCC_DHCM(i), i << 5);
+
+ /*
+ * Enable SHADOW Region 0 and only use this region
+ * This is needed to have working intr...
+ */
+ TPCC_WRITE_4(sc, EDMA_TPCC_DRAE0, 0xffffffff);
+ TPCC_WRITE_4(sc, EDMA_TPCC_DRAEH0, 0xffffffff);
+
+ return ;
+}
+
+int
+edma_comp_intr(void *arg)
+{
+ struct edma_softc *sc = arg;
+ uint32_t ipr, iprh;
+ int i;
+
+ ipr = TPCC_READ_4(sc, EDMA_TPCC_IPR);
+ iprh = TPCC_READ_4(sc, EDMA_TPCC_IPRH);
+
+ /* Lookup to intr in the first 32 chans */
+ for (i = 0; i < (EDMA_NUM_DMA_CHANS/2); i++) {
+ if (ISSET(ipr, (1<<i))) {
+ TPCC_WRITE_4(sc, EDMA_TPCC_ICR, (1<<i));
+ if (sc->sc_intr_cb[i])
+ sc->sc_intr_cb[i](sc->sc_intr_dat[i]);
+ }
+ }
+
+ for (i = 0; i < (EDMA_NUM_DMA_CHANS/2); i++) {
+ if (ISSET(iprh, (1<<i))) {
+ TPCC_WRITE_4(sc, EDMA_TPCC_ICRH, (1<<i));
+ if (sc->sc_intr_cb[i + 32])
+ sc->sc_intr_cb[i + 32](sc->sc_intr_dat[i + 32]);
+ }
+ }
+
+ /* Trig pending intr */
+ TPCC_WRITE_4(sc, EDMA_TPCC_IEVAL, 1);
+
+ return (1);
+}
+
+int
+edma_intr_dma_en(uint32_t ch, edma_intr_cb_t cb, void *dat)
+{
+ if (edma_sc == NULL || ch >= EDMA_NUM_DMA_CHANS)
+ return (EINVAL);
+
+ edma_sc->sc_intr_cb[ch] = cb;
+ edma_sc->sc_intr_dat[ch] = dat;
+
+ if (ch < 32) {
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IESR, 1 << ch);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IESR + EDMA_REG_X(0), 1 << ch);
+ } else {
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IESRH, 1 << (ch - 32));
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IESRH + EDMA_REG_X(0),
+ 1 << (ch - 32));
+ }
+
+ return (0);
+}
+
+int
+edma_intr_dma_dis(uint32_t ch)
+{
+ if (edma_sc == NULL || ch >= EDMA_NUM_DMA_CHANS)
+ return (EINVAL);
+
+ if (ch < 32)
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IECR, 1 << ch);
+ else
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IECRH, 1 << (ch - 32));
+ edma_sc->sc_intr_cb[ch] = NULL;
+ edma_sc->sc_intr_dat[ch] = NULL;
+
+ return (0);
+}
+
+int
+edma_trig_xfer_man(uint32_t ch)
+{
+ if (edma_sc == NULL || ch >= EDMA_NUM_DMA_CHANS)
+ return (EINVAL);
+
+ /*
+ * Trig xfer
+ * enable IEVAL only if there is an intr associated
+ */
+ if (ch < 32) {
+ if (ISSET(TPCC_READ_4(edma_sc, EDMA_TPCC_IER), 1 << ch))
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IEVAL, 1);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_ICR, 1 << ch);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_EMCR, 1 << ch);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_ESR, 1 << ch);
+ } else {
+ if (ISSET(TPCC_READ_4(edma_sc, EDMA_TPCC_IERH), 1 << (ch - 32)))
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IEVAL, 1);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_ICRH, 1 << (ch - 32));
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_EMCRH, 1 << (ch - 32));
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_ESRH, 1 << (ch - 32));
+ }
+
+ return (0);
+}
+
+int
+edma_trig_xfer_by_dev(uint32_t ch)
+{
+ if (edma_sc == NULL || ch >= EDMA_NUM_DMA_CHANS)
+ return (EINVAL);
+
+ if (ch < 32) {
+ if (ISSET(TPCC_READ_4(edma_sc, EDMA_TPCC_IER), 1 << ch))
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IEVAL, 1);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_ICR, 1 << ch);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_SECR, 1 << ch);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_EMCR, 1 << ch);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_EESR, 1 << ch);
+ } else {
+ if (ISSET(TPCC_READ_4(edma_sc, EDMA_TPCC_IERH), 1 << (ch - 32)))
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_IEVAL, 1);
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_ICRH, 1 << (ch - 32));
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_SECRH, 1 << (ch - 32));
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_EMCRH, 1 << (ch - 32));
+ TPCC_WRITE_4(edma_sc, EDMA_TPCC_EESRH, 1 << (ch - 32));
+ }
+ return (0);
+}
+
+void
+edma_param_write(uint32_t ch, struct edma_param *params)
+{
+ bus_space_write_region_4(edma_sc->sc_iot, edma_sc->sc_tpcc,
+ EDMA_TPCC_OPT(ch), (uint32_t *)params, 8);
+}
+
+void
+edma_param_read(uint32_t ch, struct edma_param *params)
+{
+ bus_space_read_region_4(edma_sc->sc_iot, edma_sc->sc_tpcc,
+ EDMA_TPCC_OPT(ch), (uint32_t *)params, 8);
+}
+
--- /dev/null
+/* $OpenBSD: edmavar.h,v 1.4 2015/01/22 14:33:01 krw Exp $ */
+/*
+ * Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __EDMAVAR_H__
+#define __EDMAVAR_H__
+
+typedef void (*edma_intr_cb_t)(void *);
+
+/*
+ * EDMA PaRAM dma descriptors
+ */
+struct edma_param{
+ uint32_t opt; /* Option */
+ uint32_t src; /* Ch source */
+ uint16_t acnt; /* 1st dim count */
+ uint16_t bcnt; /* 2nd dim count */
+ uint32_t dst; /* Chan dst addr */
+ int16_t srcbidx; /* Src b index */
+ int16_t dstbidx; /* Dst b index */
+ uint16_t link; /* Link addr */
+ uint16_t bcntrld; /* BCNT reload */
+ int16_t srccidx; /* Source C index */
+ int16_t dstcidx; /* Dest C index */
+ uint16_t ccnt; /* 3rd dim count */
+ uint16_t res; /* Reserved */
+} __attribute__((__packed__));
+
+int edma_intr_dma_en(uint32_t, edma_intr_cb_t, void *); /* en it for chan */
+int edma_intr_dma_dis(uint32_t); /* disable intr for chan */
+int edma_trig_xfer_man(uint32_t); /* trig a dma xfer */
+int edma_trig_xfer_by_dev(uint32_t); /* dma xfer trig by dev */
+void edma_param_write(uint32_t, struct edma_param *);
+void edma_param_read(uint32_t, struct edma_param *);
+
+#endif /* __EDMAVAR_H__ */
--- /dev/null
+# $OpenBSD: files.omap,v 1.8 2016/05/02 08:15:55 patrick Exp $
+
+define omap {}
+device omap: omap
+attach omap at fdt
+file arch/armv7/omap/omap_machdep.c omap needs-flag
+file arch/armv7/omap/omap.c omap
+file arch/armv7/omap/omap3.c
+file arch/armv7/omap/omap4.c
+file arch/armv7/omap/am335x.c
+
+device ommmc: sdmmcbus
+attach ommmc at omap
+file arch/armv7/omap/ommmc.c ommmc
+
+device cpsw: ether, ifnet, mii, ifmedia
+attach cpsw at omap
+file arch/armv7/omap/if_cpsw.c cpsw
+
+device prcm
+attach prcm at omap
+file arch/armv7/omap/prcm.c prcm
+
+device sitaracm
+attach sitaracm at omap
+file arch/armv7/omap/am335x_cm_padconf.c sitaracm
+file arch/armv7/omap/sitara_cm.c sitaracm
+
+device omgpio: gpiobus
+attach omgpio at omap
+file arch/armv7/omap/omgpio.c omgpio
+
+device tiiic: i2cbus
+attach tiiic at omap
+file arch/armv7/omap/ti_iic.c tiiic
+
+device edma
+attach edma at omap
+file arch/armv7/omap/edma.c edma
+
+device intc
+attach intc at omap
+file arch/armv7/omap/intc.c intc
+
+device gptimer
+attach gptimer at omap
+file arch/armv7/omap/gptimer.c gptimer
+
+device dmtimer
+attach dmtimer at omap
+file arch/armv7/omap/dmtimer.c dmtimer
+
+device omapid
+attach omapid at omap
+file arch/armv7/omap/omapid.c omapid
+
+device omdog
+attach omdog at omap
+file arch/armv7/omap/omdog.c omdog
+
+attach ohci at omap with omohci
+file arch/armv7/omap/omohci.c omohci
+
+attach ehci at omap with omehci
+file arch/armv7/omap/omehci.c omehci
+
+# NS16550 compatible serial ports
+attach com at omap with com_omap
+file arch/armv7/omap/omap_com.c com_omap
+
+device omusbtll
+attach omusbtll at omap
+file arch/armv7/omap/omusbtll.c omusbtll
+
+device omkbd: wskbddev
+attach omkbd at omap
+file arch/armv7/omap/omkbd.c omkbd
+
+# LCD frame buffer
+device omdisplay: wsemuldisplaydev, rasops16
+attach omdisplay at omap
+file arch/armv7/omap/omdisplay.c omdisplay
+
+# MCSPI - spi
+device mcspi
+attach mcspi at omap
+file arch/armv7/omap/mcspi.c mcspi
+
+# pseudo-Audio Device Driver
+device oaudio: audio
+attach oaudio at omap # configure after Atlas Driver
+file arch/armv7/omap/beagle_audio.c oaudio
--- /dev/null
+/* $OpenBSD: gptimer.c,v 1.4 2014/06/20 14:08:11 rapha Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * WARNING - this timer initializion has not been checked
+ * to see if it will do _ANYTHING_ sane if the omap enters
+ * low power mode.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+#include <sys/evcount.h>
+#include <sys/device.h>
+#include <sys/timetc.h>
+#include <dev/clock_subr.h>
+#include <machine/bus.h>
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/prcmvar.h>
+
+#include <machine/intr.h>
+#include <arm/cpufunc.h>
+
+/* registers */
+#define GP_TIDR 0x000
+#define GP_TIDR_REV 0xff
+#define GP_TIOCP_CFG 0x010
+#define GP_TIOCP_CFG_CLKA 0x000000300
+#define GP_TIOCP_CFG_EMUFREE 0x000000020
+#define GP_TIOCP_CFG_IDLEMODE 0x000000018
+#define GP_TIOCP_CFG_ENAPWAKEUP 0x000000004
+#define GP_TIOCP_CFG_SOFTRESET 0x000000002
+#define GP_TIOCP_CFG_AUTOIDLE 0x000000001
+#define GP_TISTAT 0x014
+#define GP_TISTAT_RESETDONE 0x000000001
+#define GP_TISR 0x018
+#define GP_TISTAT_TCAR 0x00000004
+#define GP_TISTAT_OVF 0x00000002
+#define GP_TISTAT_MATCH 0x00000001
+#define GP_TIER 0x1c
+#define GP_TIER_TCAR_EN 0x4
+#define GP_TIER_OVF_EN 0x2
+#define GP_TIER_MAT_EN 0x1
+#define GP_TWER 0x020
+#define GP_TWER_TCAR_EN 0x00000004
+#define GP_TWER_OVF_EN 0x00000002
+#define GP_TWER_MAT_EN 0x00000001
+#define GP_TCLR 0x024
+#define GP_TCLR_GPO (1<<14)
+#define GP_TCLR_CAPT (1<<13)
+#define GP_TCLR_PT (1<<12)
+#define GP_TCLR_TRG (3<<10)
+#define GP_TCLR_TRG_O (1<<10)
+#define GP_TCLR_TRG_OM (2<<10)
+#define GP_TCLR_TCM (3<<8)
+#define GP_TCLR_TCM_RISE (1<<8)
+#define GP_TCLR_TCM_FALL (2<<8)
+#define GP_TCLR_TCM_BOTH (3<<8)
+#define GP_TCLR_SCPWM (1<<7)
+#define GP_TCLR_CE (1<<6)
+#define GP_TCLR_PRE (1<<5)
+#define GP_TCLR_PTV (7<<2)
+#define GP_TCLR_AR (1<<1)
+#define GP_TCLR_ST (1<<0)
+#define GP_TCRR 0x028 /* counter */
+#define GP_TLDR 0x02c /* reload */
+#define GP_TTGR 0x030
+#define GP_TWPS 0x034
+#define GP_TWPS_TCLR 0x01
+#define GP_TWPS_TCRR 0x02
+#define GP_TWPS_TLDR 0x04
+#define GP_TWPS_TTGR 0x08
+#define GP_TWPS_TMAR 0x10
+#define GP_TWPS_ALL 0x1f
+#define GP_TMAR 0x038
+#define GP_TCAR 0x03C
+#define GP_TSICR 0x040
+#define GP_TSICR_POSTED 0x00000002
+#define GP_TSICR_SFT 0x00000001
+#define GP_TCAR2 0x044
+
+#define TIMER_FREQUENCY 32768 /* 32kHz is used, selectable */
+
+static struct evcount clk_count;
+static struct evcount stat_count;
+#define GPT1_IRQ 38
+#define GPTIMER0_IRQ 38
+
+//static int clk_irq = GPT1_IRQ; /* XXX 37 */
+
+void gptimer_attach(struct device *parent, struct device *self, void *args);
+int gptimer_intr(void *frame);
+void gptimer_wait(int reg);
+void gptimer_cpu_initclocks(void);
+void gptimer_delay(u_int);
+void gptimer_setstatclockrate(int newhz);
+
+bus_space_tag_t gptimer_iot;
+bus_space_handle_t gptimer_ioh0, gptimer_ioh1;
+int gptimer_irq = 0;
+
+u_int gptimer_get_timecount(struct timecounter *);
+
+static struct timecounter gptimer_timecounter = {
+ gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL
+};
+
+volatile u_int32_t nexttickevent;
+volatile u_int32_t nextstatevent;
+u_int32_t ticks_per_second;
+u_int32_t ticks_per_intr;
+u_int32_t ticks_err_cnt;
+u_int32_t ticks_err_sum;
+u_int32_t statvar, statmin;
+
+struct cfattach gptimer_ca = {
+ sizeof (struct device), NULL, gptimer_attach
+};
+
+struct cfdriver gptimer_cd = {
+ NULL, "gptimer", DV_DULL
+};
+
+void
+gptimer_attach(struct device *parent, struct device *self, void *args)
+{
+ struct armv7_attach_args *aa = args;
+ bus_space_handle_t ioh;
+ u_int32_t rev;
+
+ gptimer_iot = aa->aa_iot;
+ if (bus_space_map(gptimer_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &ioh))
+ panic("gptimer_attach: bus_space_map failed!");
+
+ rev = bus_space_read_4(gptimer_iot, ioh, GP_TIDR);
+
+ printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
+ if (self->dv_unit == 0) {
+ gptimer_ioh0 = ioh;
+ gptimer_irq = aa->aa_dev->irq[0];
+ bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR, 0);
+ } else if (self->dv_unit == 1) {
+ /* start timer because it is used in delay */
+ gptimer_ioh1 = ioh;
+ bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TCRR, 0);
+ gptimer_wait(GP_TWPS_ALL);
+ bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TLDR, 0);
+ gptimer_wait(GP_TWPS_ALL);
+ bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TCLR,
+ GP_TCLR_AR | GP_TCLR_ST);
+ gptimer_wait(GP_TWPS_ALL);
+
+ gptimer_timecounter.tc_frequency = TIMER_FREQUENCY;
+ tc_init(&gptimer_timecounter);
+ }
+ else
+ panic("attaching too many gptimers at 0x%lx",
+ aa->aa_dev->mem[0].addr);
+
+ arm_clock_register(gptimer_cpu_initclocks, gptimer_delay,
+ gptimer_setstatclockrate, NULL);
+}
+
+/*
+ * See comment in arm/xscale/i80321_clock.c
+ *
+ * counter is count up, but with autoreload timers it is not possible
+ * to detect how many interrupts passed while interrupts were blocked.
+ * also it is not possible to atomically add to the register
+ * get get it to precisely fire at a non-fixed interval.
+ *
+ * To work around this two timers are used, GPT1 is used as a reference
+ * clock without reload , however we just ignore the interrupt it
+ * would (may?) generate.
+ *
+ * Internally this keeps track of when the next timer should fire
+ * and based on that time and the current value of the reference
+ * clock a number is written into the timer count register to schedule
+ * the next event.
+ */
+
+int
+gptimer_intr(void *frame)
+{
+ u_int32_t now, r;
+ u_int32_t nextevent, duration;
+
+ /* clear interrupt */
+ now = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
+
+ while ((int32_t) (nexttickevent - now) < 0) {
+ nexttickevent += ticks_per_intr;
+ ticks_err_sum += ticks_err_cnt;
+#if 0
+ if (ticks_err_sum > hz) {
+ u_int32_t match_error;
+ match_error = ticks_err_sum / hz
+ ticks_err_sum -= (match_error * hz);
+ }
+#else
+ /* looping a few times is faster than divide */
+ while (ticks_err_sum > hz) {
+ nexttickevent += 1;
+ ticks_err_sum -= hz;
+ }
+#endif
+ clk_count.ec_count++;
+ hardclock(frame);
+ }
+ while ((int32_t) (nextstatevent - now) < 0) {
+ do {
+ r = random() & (statvar -1);
+ } while (r == 0); /* random == 0 not allowed */
+ nextstatevent += statmin + r;
+ /* XXX - correct nextstatevent? */
+ stat_count.ec_count++;
+ statclock(frame);
+ }
+ if ((nexttickevent - now) < (nextstatevent - now))
+ nextevent = nexttickevent;
+ else
+ nextevent = nextstatevent;
+
+/* XXX */
+ duration = nextevent -
+ bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
+#if 0
+ printf("duration 0x%x %x %x\n", nextevent -
+ bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR),
+ bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TCRR),
+ bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR));
+#endif
+
+
+ if (duration <= 0)
+ duration = 1; /* trigger immediately. */
+
+ if (duration > ticks_per_intr) {
+ /*
+ * If interrupts are blocked too long, like during
+ * the root prompt or ddb, the timer can roll over,
+ * this will allow the system to continue to run
+ * even if time is lost.
+ */
+ duration = ticks_per_intr;
+ nexttickevent = now;
+ nextstatevent = now;
+ }
+
+ gptimer_wait(GP_TWPS_ALL);
+ bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR,
+ bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR));
+ gptimer_wait(GP_TWPS_ALL);
+ bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -duration);
+
+ return 1;
+}
+
+/*
+ * would be interesting to play with trigger mode while having one timer
+ * in 32KHz mode, and the other timer running in sysclk mode and use
+ * the high resolution speeds (matters more for delay than tick timer
+ */
+
+void
+gptimer_cpu_initclocks()
+{
+// u_int32_t now;
+ stathz = 128;
+ profhz = 1024;
+
+ ticks_per_second = TIMER_FREQUENCY;
+
+ setstatclockrate(stathz);
+
+ ticks_per_intr = ticks_per_second / hz;
+ ticks_err_cnt = ticks_per_second % hz;
+ ticks_err_sum = 0;;
+
+ prcm_setclock(1, PRCM_CLK_SPEED_32);
+ prcm_setclock(2, PRCM_CLK_SPEED_32);
+ /* establish interrupts */
+ arm_intr_establish(gptimer_irq, IPL_CLOCK, gptimer_intr,
+ NULL, "tick");
+
+ /* setup timer 0 (hardware timer 2) */
+ /* reset? - XXX */
+
+ bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TLDR, 0);
+
+ nexttickevent = nextstatevent = bus_space_read_4(gptimer_iot,
+ gptimer_ioh1, GP_TCRR) + ticks_per_intr;
+
+ gptimer_wait(GP_TWPS_ALL);
+ bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TIER, GP_TIER_OVF_EN);
+ gptimer_wait(GP_TWPS_ALL);
+ bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TWER, GP_TWER_OVF_EN);
+ gptimer_wait(GP_TWPS_ALL);
+ bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR,
+ GP_TCLR_AR | GP_TCLR_ST);
+ gptimer_wait(GP_TWPS_ALL);
+ bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR,
+ bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR));
+ gptimer_wait(GP_TWPS_ALL);
+ bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -ticks_per_intr);
+ gptimer_wait(GP_TWPS_ALL);
+}
+
+void
+gptimer_wait(int reg)
+{
+ while (bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TWPS) & reg)
+ ;
+}
+
+#if 0
+void
+microtime(struct timeval *tvp)
+{
+ int s;
+ int deltacnt;
+ u_int32_t counter, expected;
+ s = splhigh();
+
+ if (1) { /* not inited */
+ tvp->tv_sec = 0;
+ tvp->tv_usec = 0;
+ return;
+ }
+ s = splhigh();
+ counter = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
+ expected = nexttickevent;
+
+ *tvp = time;
+ splx(s);
+
+ deltacnt = counter - expected + ticks_per_intr;
+
+#if 1
+ /* low frequency timer algorithm */
+ tvp->tv_usec += deltacnt * 1000000ULL / TIMER_FREQUENCY;
+#else
+ /* high frequency timer algorithm - XXX */
+ tvp->tv_usec += deltacnt / (TIMER_FREQUENCY / 1000000ULL);
+#endif
+
+ while (tvp->tv_usec >= 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+
+}
+#endif
+
+void
+gptimer_delay(u_int usecs)
+{
+ u_int32_t clock, oclock, delta, delaycnt;
+ volatile int j;
+ int csec, usec;
+
+ if (usecs > (0x80000000 / (TIMER_FREQUENCY))) {
+ csec = usecs / 10000;
+ usec = usecs % 10000;
+
+ delaycnt = (TIMER_FREQUENCY / 100) * csec +
+ (TIMER_FREQUENCY / 100) * usec / 10000;
+ } else {
+ delaycnt = TIMER_FREQUENCY * usecs / 1000000;
+ }
+ if (delaycnt <= 1)
+ for (j = 100; j > 0; j--)
+ ;
+
+ if (gptimer_ioh1 == 0) {
+ /* BAH */
+ for (; usecs > 0; usecs--)
+ for (j = 100; j > 0; j--)
+ ;
+ return;
+ }
+ oclock = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
+ while (1) {
+ for (j = 100; j > 0; j--)
+ ;
+ clock = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
+ delta = clock - oclock;
+ if (delta > delaycnt)
+ break;
+ }
+
+}
+
+void
+gptimer_setstatclockrate(int newhz)
+{
+ int minint, statint;
+ int s;
+
+ s = splclock();
+
+ statint = ticks_per_second / newhz;
+ /* calculate largest 2^n which is smaller that just over half statint */
+ statvar = 0x40000000; /* really big power of two */
+ minint = statint / 2 + 100;
+ while (statvar > minint)
+ statvar >>= 1;
+
+ statmin = statint - (statvar >> 1);
+
+ splx(s);
+
+ /*
+ * XXX this allows the next stat timer to occur then it switches
+ * to the new frequency. Rather than switching instantly.
+ */
+}
+
+
+u_int
+gptimer_get_timecount(struct timecounter *tc)
+{
+ return bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR);
+}
--- /dev/null
+/* $OpenBSD: if_cpsw.c,v 1.34 2016/04/13 11:33:59 mpi Exp $ */
+/* $NetBSD: if_cpsw.c,v 1.3 2013/04/17 14:36:34 bouyer Exp $ */
+
+/*
+ * Copyright (c) 2013 Jonathan A. Kollasch
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
+ * 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 "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/pool.h>
+#include <sys/queue.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/timeout.h>
+#include <sys/socket.h>
+
+#include <machine/bus.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <arch/armv7/armv7/armv7var.h>
+#include <arch/armv7/omap/sitara_cm.h>
+#include <arch/armv7/omap/if_cpswreg.h>
+
+#define CPSW_TXFRAGS 16
+
+#define OMAP2SCM_MAC_ID0_LO 0x630
+#define OMAP2SCM_MAC_ID0_HI 0x634
+
+#define CPSW_CPPI_RAM_SIZE (0x2000)
+#define CPSW_CPPI_RAM_TXDESCS_SIZE (CPSW_CPPI_RAM_SIZE/2)
+#define CPSW_CPPI_RAM_RXDESCS_SIZE \
+ (CPSW_CPPI_RAM_SIZE - CPSW_CPPI_RAM_TXDESCS_SIZE)
+#define CPSW_CPPI_RAM_TXDESCS_BASE (CPSW_CPPI_RAM_OFFSET + 0x0000)
+#define CPSW_CPPI_RAM_RXDESCS_BASE \
+ (CPSW_CPPI_RAM_OFFSET + CPSW_CPPI_RAM_TXDESCS_SIZE)
+
+#define CPSW_NTXDESCS (CPSW_CPPI_RAM_TXDESCS_SIZE/sizeof(struct cpsw_cpdma_bd))
+#define CPSW_NRXDESCS (CPSW_CPPI_RAM_RXDESCS_SIZE/sizeof(struct cpsw_cpdma_bd))
+
+#define CPSW_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN)
+
+#define TXDESC_NEXT(x) cpsw_txdesc_adjust((x), 1)
+#define TXDESC_PREV(x) cpsw_txdesc_adjust((x), -1)
+
+#define RXDESC_NEXT(x) cpsw_rxdesc_adjust((x), 1)
+#define RXDESC_PREV(x) cpsw_rxdesc_adjust((x), -1)
+
+struct cpsw_ring_data {
+ bus_dmamap_t tx_dm[CPSW_NTXDESCS];
+ struct mbuf *tx_mb[CPSW_NTXDESCS];
+ bus_dmamap_t rx_dm[CPSW_NRXDESCS];
+ struct mbuf *rx_mb[CPSW_NRXDESCS];
+};
+
+struct cpsw_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ bus_dma_tag_t sc_bdt;
+ bus_space_handle_t sc_bsh_txdescs;
+ bus_space_handle_t sc_bsh_rxdescs;
+ bus_addr_t sc_txdescs_pa;
+ bus_addr_t sc_rxdescs_pa;
+
+ struct arpcom sc_ac;
+ struct mii_data sc_mii;
+
+ struct cpsw_ring_data *sc_rdp;
+ volatile u_int sc_txnext;
+ volatile u_int sc_txhead;
+ volatile u_int sc_rxhead;
+
+ void *sc_rxthih;
+ void *sc_rxih;
+ void *sc_txih;
+ void *sc_miscih;
+
+ void *sc_txpad;
+ bus_dmamap_t sc_txpad_dm;
+#define sc_txpad_pa sc_txpad_dm->dm_segs[0].ds_addr
+
+ volatile bool sc_txrun;
+ volatile bool sc_rxrun;
+ volatile bool sc_txeoq;
+ volatile bool sc_rxeoq;
+ struct timeout sc_tick;
+ int sc_active_port;
+};
+
+#define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
+
+void cpsw_attach(struct device *, struct device *, void *);
+
+void cpsw_start(struct ifnet *);
+int cpsw_ioctl(struct ifnet *, u_long, caddr_t);
+void cpsw_watchdog(struct ifnet *);
+int cpsw_init(struct ifnet *);
+void cpsw_stop(struct ifnet *);
+
+int cpsw_mii_readreg(struct device *, int, int);
+void cpsw_mii_writereg(struct device *, int, int, int);
+void cpsw_mii_statchg(struct device *);
+
+void cpsw_tick(void *);
+
+int cpsw_new_rxbuf(struct cpsw_softc * const, const u_int);
+int cpsw_mediachange(struct ifnet *);
+void cpsw_mediastatus(struct ifnet *, struct ifmediareq *);
+
+int cpsw_rxthintr(void *);
+int cpsw_rxintr(void *);
+int cpsw_txintr(void *);
+int cpsw_miscintr(void *);
+
+void cpsw_get_mac_addr(struct cpsw_softc *);
+
+struct cfattach cpsw_ca = {
+ sizeof(struct cpsw_softc),
+ NULL,
+ cpsw_attach
+};
+
+struct cfdriver cpsw_cd = {
+ NULL,
+ "cpsw",
+ DV_IFNET
+};
+
+static inline u_int
+cpsw_txdesc_adjust(u_int x, int y)
+{
+ return (((x) + y) & (CPSW_NTXDESCS - 1));
+}
+
+static inline u_int
+cpsw_rxdesc_adjust(u_int x, int y)
+{
+ return (((x) + y) & (CPSW_NRXDESCS - 1));
+}
+
+static inline void
+cpsw_set_txdesc_next(struct cpsw_softc * const sc, const u_int i, uint32_t n)
+{
+ const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i + 0;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh_txdescs, o, n);
+}
+
+static inline void
+cpsw_set_rxdesc_next(struct cpsw_softc * const sc, const u_int i, uint32_t n)
+{
+ const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i + 0;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh_rxdescs, o, n);
+}
+
+static inline void
+cpsw_get_txdesc(struct cpsw_softc * const sc, const u_int i,
+ struct cpsw_cpdma_bd * const bdp)
+{
+ const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i;
+ bus_space_read_region_4(sc->sc_bst, sc->sc_bsh_txdescs, o,
+ (uint32_t *)bdp, 4);
+}
+
+static inline void
+cpsw_set_txdesc(struct cpsw_softc * const sc, const u_int i,
+ struct cpsw_cpdma_bd * const bdp)
+{
+ const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i;
+ bus_space_write_region_4(sc->sc_bst, sc->sc_bsh_txdescs, o,
+ (uint32_t *)bdp, 4);
+}
+
+static inline void
+cpsw_get_rxdesc(struct cpsw_softc * const sc, const u_int i,
+ struct cpsw_cpdma_bd * const bdp)
+{
+ const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i;
+ bus_space_read_region_4(sc->sc_bst, sc->sc_bsh_rxdescs, o,
+ (uint32_t *)bdp, 4);
+}
+
+static inline void
+cpsw_set_rxdesc(struct cpsw_softc * const sc, const u_int i,
+ struct cpsw_cpdma_bd * const bdp)
+{
+ const bus_size_t o = sizeof(struct cpsw_cpdma_bd) * i;
+ bus_space_write_region_4(sc->sc_bst, sc->sc_bsh_rxdescs, o,
+ (uint32_t *)bdp, 4);
+}
+
+static inline bus_addr_t
+cpsw_txdesc_paddr(struct cpsw_softc * const sc, u_int x)
+{
+ KASSERT(x < CPSW_NTXDESCS);
+ return sc->sc_txdescs_pa + sizeof(struct cpsw_cpdma_bd) * x;
+}
+
+static inline bus_addr_t
+cpsw_rxdesc_paddr(struct cpsw_softc * const sc, u_int x)
+{
+ KASSERT(x < CPSW_NRXDESCS);
+ return sc->sc_rxdescs_pa + sizeof(struct cpsw_cpdma_bd) * x;
+}
+
+void
+cpsw_get_mac_addr(struct cpsw_softc *sc)
+{
+ struct arpcom *ac = &sc->sc_ac;
+ u_int32_t mac_lo = 0, mac_hi = 0;
+
+ sitara_cm_reg_read_4(OMAP2SCM_MAC_ID0_LO, &mac_lo);
+ sitara_cm_reg_read_4(OMAP2SCM_MAC_ID0_HI, &mac_hi);
+
+ if ((mac_lo == 0) && (mac_hi == 0))
+ printf("%s: invalid ethernet address\n", DEVNAME(sc));
+ else {
+ ac->ac_enaddr[0] = (mac_hi >> 0) & 0xff;
+ ac->ac_enaddr[1] = (mac_hi >> 8) & 0xff;
+ ac->ac_enaddr[2] = (mac_hi >> 16) & 0xff;
+ ac->ac_enaddr[3] = (mac_hi >> 24) & 0xff;
+ ac->ac_enaddr[4] = (mac_lo >> 0) & 0xff;
+ ac->ac_enaddr[5] = (mac_lo >> 8) & 0xff;
+ }
+}
+
+static void
+cpsw_mdio_init(struct cpsw_softc *sc)
+{
+ uint32_t alive, link;
+ u_int tries;
+
+ sc->sc_active_port = 0;
+
+ /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
+ /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOCONTROL,
+ (1<<30) | (1<<18) | 0xFF);
+
+ for(tries = 0; tries < 1000; tries++) {
+ alive = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOALIVE) & 3;
+ if (alive)
+ break;
+ delay(1);
+ }
+
+ if (alive == 0) {
+ printf("%s: no PHY is alive\n", DEVNAME(sc));
+ return;
+ }
+
+ link = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOLINK) & 3;
+
+ if (alive == 3) {
+ /* both ports are alive, prefer one with link */
+ if (link == 2)
+ sc->sc_active_port = 1;
+ } else if (alive == 2)
+ sc->sc_active_port = 1;
+
+ /* Select the port to monitor */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOUSERPHYSEL0,
+ sc->sc_active_port);
+}
+
+void
+cpsw_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct cpsw_softc *sc = (struct cpsw_softc *)self;
+ struct armv7_attach_args *aa = aux;
+ struct arpcom * const ac = &sc->sc_ac;
+ struct ifnet * const ifp = &ac->ac_if;
+ u_int32_t idver;
+ int error;
+ u_int i;
+
+ timeout_set(&sc->sc_tick, cpsw_tick, sc);
+
+ cpsw_get_mac_addr(sc);
+
+ sc->sc_rxthih = arm_intr_establish(aa->aa_dev->irq[0] +
+ CPSW_INTROFF_RXTH, IPL_NET, cpsw_rxthintr, sc, DEVNAME(sc));
+ sc->sc_rxih = arm_intr_establish(aa->aa_dev->irq[0] +
+ CPSW_INTROFF_RX, IPL_NET, cpsw_rxintr, sc, DEVNAME(sc));
+ sc->sc_txih = arm_intr_establish(aa->aa_dev->irq[0] +
+ CPSW_INTROFF_TX, IPL_NET, cpsw_txintr, sc, DEVNAME(sc));
+ sc->sc_miscih = arm_intr_establish(aa->aa_dev->irq[0] +
+ CPSW_INTROFF_MISC, IPL_NET, cpsw_miscintr, sc, DEVNAME(sc));
+
+ sc->sc_bst = aa->aa_iot;
+ sc->sc_bdt = aa->aa_dmat;
+
+ error = bus_space_map(sc->sc_bst, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_bsh);
+ if (error) {
+ printf("can't map registers: %d\n", error);
+ return;
+ }
+
+ sc->sc_txdescs_pa = aa->aa_dev->mem[0].addr +
+ CPSW_CPPI_RAM_TXDESCS_BASE;
+ error = bus_space_subregion(sc->sc_bst, sc->sc_bsh,
+ CPSW_CPPI_RAM_TXDESCS_BASE, CPSW_CPPI_RAM_TXDESCS_SIZE,
+ &sc->sc_bsh_txdescs);
+ if (error) {
+ printf("can't subregion tx ring SRAM: %d\n", error);
+ return;
+ }
+
+ sc->sc_rxdescs_pa = aa->aa_dev->mem[0].addr +
+ CPSW_CPPI_RAM_RXDESCS_BASE;
+ error = bus_space_subregion(sc->sc_bst, sc->sc_bsh,
+ CPSW_CPPI_RAM_RXDESCS_BASE, CPSW_CPPI_RAM_RXDESCS_SIZE,
+ &sc->sc_bsh_rxdescs);
+ if (error) {
+ printf("can't subregion rx ring SRAM: %d\n", error);
+ return;
+ }
+
+ sc->sc_rdp = malloc(sizeof(*sc->sc_rdp), M_TEMP, M_WAITOK);
+ KASSERT(sc->sc_rdp != NULL);
+
+ for (i = 0; i < CPSW_NTXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_bdt, MCLBYTES,
+ CPSW_TXFRAGS, MCLBYTES, 0, 0,
+ &sc->sc_rdp->tx_dm[i])) != 0) {
+ printf("unable to create tx DMA map: %d\n", error);
+ }
+ sc->sc_rdp->tx_mb[i] = NULL;
+ }
+
+ for (i = 0; i < CPSW_NRXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_bdt, MCLBYTES, 1,
+ MCLBYTES, 0, 0, &sc->sc_rdp->rx_dm[i])) != 0) {
+ printf("unable to create rx DMA map: %d\n", error);
+ }
+ sc->sc_rdp->rx_mb[i] = NULL;
+ }
+
+ sc->sc_txpad = dma_alloc(ETHER_MIN_LEN, PR_WAITOK | PR_ZERO);
+ KASSERT(sc->sc_txpad != NULL);
+ bus_dmamap_create(sc->sc_bdt, ETHER_MIN_LEN, 1, ETHER_MIN_LEN, 0,
+ BUS_DMA_WAITOK, &sc->sc_txpad_dm);
+ bus_dmamap_load(sc->sc_bdt, sc->sc_txpad_dm, sc->sc_txpad,
+ ETHER_MIN_LEN, NULL, BUS_DMA_WAITOK|BUS_DMA_WRITE);
+ bus_dmamap_sync(sc->sc_bdt, sc->sc_txpad_dm, 0, ETHER_MIN_LEN,
+ BUS_DMASYNC_PREWRITE);
+
+ idver = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_IDVER);
+ printf(": version %d.%d (%d), address %s\n",
+ CPSW_SS_IDVER_MAJ(idver), CPSW_SS_IDVER_MIN(idver),
+ CPSW_SS_IDVER_RTL(idver), ether_sprintf(ac->ac_enaddr));
+
+ ifp->if_softc = sc;
+ ifp->if_capabilities = 0;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = cpsw_start;
+ ifp->if_ioctl = cpsw_ioctl;
+ ifp->if_watchdog = cpsw_watchdog;
+ IFQ_SET_MAXLEN(&ifp->if_snd, CPSW_NTXDESCS - 1);
+ memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
+
+ cpsw_stop(ifp);
+
+ sc->sc_mii.mii_ifp = ifp;
+ sc->sc_mii.mii_readreg = cpsw_mii_readreg;
+ sc->sc_mii.mii_writereg = cpsw_mii_writereg;
+ sc->sc_mii.mii_statchg = cpsw_mii_statchg;
+
+ cpsw_mdio_init(sc);
+
+ ifmedia_init(&sc->sc_mii.mii_media, 0, cpsw_mediachange,
+ cpsw_mediastatus);
+ mii_attach(self, &sc->sc_mii, 0xffffffff,
+ MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
+ printf("no PHY found!\n");
+ ifmedia_add(&sc->sc_mii.mii_media,
+ IFM_ETHER|IFM_MANUAL, 0, NULL);
+ ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL);
+ } else {
+ ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
+ }
+
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+ return;
+}
+
+int
+cpsw_mediachange(struct ifnet *ifp)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
+
+ if (LIST_FIRST(&sc->sc_mii.mii_phys))
+ mii_mediachg(&sc->sc_mii);
+
+ return (0);
+}
+
+void
+cpsw_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
+
+ if (LIST_FIRST(&sc->sc_mii.mii_phys)) {
+ mii_pollstat(&sc->sc_mii);
+ ifmr->ifm_active = sc->sc_mii.mii_media_active;
+ ifmr->ifm_status = sc->sc_mii.mii_media_status;
+ }
+}
+
+void
+cpsw_start(struct ifnet *ifp)
+{
+ struct cpsw_softc * const sc = ifp->if_softc;
+ struct cpsw_ring_data * const rdp = sc->sc_rdp;
+ struct cpsw_cpdma_bd bd;
+ struct mbuf *m;
+ bus_dmamap_t dm;
+ u_int eopi = ~0;
+ u_int seg;
+ u_int txfree;
+ int txstart = -1;
+ int error;
+ bool pad;
+ u_int mlen;
+
+ if (!ISSET(ifp->if_flags, IFF_RUNNING) ||
+ ifq_is_oactive(&ifp->if_snd) ||
+ IFQ_IS_EMPTY(&ifp->if_snd))
+ return;
+
+ if (sc->sc_txnext >= sc->sc_txhead)
+ txfree = CPSW_NTXDESCS - 1 + sc->sc_txhead - sc->sc_txnext;
+ else
+ txfree = sc->sc_txhead - sc->sc_txnext - 1;
+
+ for (;;) {
+ if (txfree <= CPSW_TXFRAGS) {
+ ifq_set_oactive(&ifp->if_snd);
+ break;
+ }
+
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+
+ dm = rdp->tx_dm[sc->sc_txnext];
+ error = bus_dmamap_load_mbuf(sc->sc_bdt, dm, m, BUS_DMA_NOWAIT);
+ switch (error) {
+ case 0:
+ break;
+
+ case EFBIG: /* mbuf chain is too fragmented */
+ if (m_defrag(m, M_DONTWAIT) == 0 &&
+ bus_dmamap_load_mbuf(sc->sc_bdt, dm, m,
+ BUS_DMA_NOWAIT) == 0)
+ break;
+
+ /* FALLTHROUGH */
+ default:
+ m_freem(m);
+ ifp->if_oerrors++;
+ continue;
+ }
+
+ mlen = dm->dm_mapsize;
+ pad = mlen < CPSW_PAD_LEN;
+
+ KASSERT(rdp->tx_mb[sc->sc_txnext] == NULL);
+ rdp->tx_mb[sc->sc_txnext] = m;
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif
+
+ bus_dmamap_sync(sc->sc_bdt, dm, 0, dm->dm_mapsize,
+ BUS_DMASYNC_PREWRITE);
+
+ if (txstart == -1)
+ txstart = sc->sc_txnext;
+ eopi = sc->sc_txnext;
+ for (seg = 0; seg < dm->dm_nsegs; seg++) {
+ bd.next = cpsw_txdesc_paddr(sc,
+ TXDESC_NEXT(sc->sc_txnext));
+ bd.bufptr = dm->dm_segs[seg].ds_addr;
+ bd.bufoff = 0;
+ bd.buflen = dm->dm_segs[seg].ds_len;
+ bd.pktlen = 0;
+ bd.flags = 0;
+
+ if (seg == 0) {
+ bd.flags = CPDMA_BD_OWNER | CPDMA_BD_SOP;
+ bd.pktlen = MAX(mlen, CPSW_PAD_LEN);
+ }
+
+ if (seg == dm->dm_nsegs - 1 && !pad)
+ bd.flags |= CPDMA_BD_EOP;
+
+ cpsw_set_txdesc(sc, sc->sc_txnext, &bd);
+ txfree--;
+ eopi = sc->sc_txnext;
+ sc->sc_txnext = TXDESC_NEXT(sc->sc_txnext);
+ }
+ if (pad) {
+ bd.next = cpsw_txdesc_paddr(sc,
+ TXDESC_NEXT(sc->sc_txnext));
+ bd.bufptr = sc->sc_txpad_pa;
+ bd.bufoff = 0;
+ bd.buflen = CPSW_PAD_LEN - mlen;
+ bd.pktlen = 0;
+ bd.flags = CPDMA_BD_EOP;
+
+ cpsw_set_txdesc(sc, sc->sc_txnext, &bd);
+ txfree--;
+ eopi = sc->sc_txnext;
+ sc->sc_txnext = TXDESC_NEXT(sc->sc_txnext);
+ }
+ }
+
+ if (txstart >= 0) {
+ ifp->if_timer = 5;
+ /* terminate the new chain */
+ KASSERT(eopi == TXDESC_PREV(sc->sc_txnext));
+ cpsw_set_txdesc_next(sc, TXDESC_PREV(sc->sc_txnext), 0);
+
+ /* link the new chain on */
+ cpsw_set_txdesc_next(sc, TXDESC_PREV(txstart),
+ cpsw_txdesc_paddr(sc, txstart));
+ if (sc->sc_txeoq) {
+ /* kick the dma engine */
+ sc->sc_txeoq = false;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0),
+ cpsw_txdesc_paddr(sc, txstart));
+ }
+ }
+}
+
+int
+cpsw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int s = splnet();
+ int error = 0;
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ /* FALLTHROUGH */
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_flags & IFF_RUNNING)
+ error = ENETRESET;
+ else
+ cpsw_init(ifp);
+ } else {
+ if (ifp->if_flags & IFF_RUNNING)
+ cpsw_stop(ifp);
+ }
+ break;
+ case SIOCSIFMEDIA:
+ ifr->ifr_media &= ~IFM_ETH_FMASK;
+ /* FALLTHROUGH */
+ case SIOCGIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
+ break;
+ default:
+ error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
+ break;
+ }
+ if (error == ENETRESET) {
+ if (ifp->if_flags & IFF_RUNNING)
+ cpsw_init(ifp);
+ error = 0;
+ }
+
+ splx(s);
+
+ return error;
+}
+
+void
+cpsw_watchdog(struct ifnet *ifp)
+{
+ printf("%s: device timeout\n", ifp->if_xname);
+
+ ifp->if_oerrors++;
+ cpsw_init(ifp);
+ cpsw_start(ifp);
+}
+
+static int
+cpsw_mii_wait(struct cpsw_softc * const sc, int reg)
+{
+ u_int tries;
+
+ for(tries = 0; tries < 1000; tries++) {
+ if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg) & (1U << 31)) == 0)
+ return 0;
+ delay(1);
+ }
+ return ETIMEDOUT;
+}
+
+int
+cpsw_mii_readreg(struct device *dev, int phy, int reg)
+{
+ struct cpsw_softc * const sc = (struct cpsw_softc *)dev;
+ uint32_t v;
+
+ if (cpsw_mii_wait(sc, MDIOUSERACCESS0) != 0)
+ return 0;
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOUSERACCESS0, (1U << 31) |
+ ((reg & 0x1F) << 21) | ((phy & 0x1F) << 16));
+
+ if (cpsw_mii_wait(sc, MDIOUSERACCESS0) != 0)
+ return 0;
+
+ v = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOUSERACCESS0);
+ if (v & (1 << 29))
+ return v & 0xffff;
+ else
+ return 0;
+}
+
+void
+cpsw_mii_writereg(struct device *dev, int phy, int reg, int val)
+{
+ struct cpsw_softc * const sc = (struct cpsw_softc *)dev;
+ uint32_t v;
+
+ KASSERT((val & 0xffff0000UL) == 0);
+
+ if (cpsw_mii_wait(sc, MDIOUSERACCESS0) != 0)
+ goto out;
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, MDIOUSERACCESS0, (1U << 31) | (1 << 30) |
+ ((reg & 0x1F) << 21) | ((phy & 0x1F) << 16) | val);
+
+ if (cpsw_mii_wait(sc, MDIOUSERACCESS0) != 0)
+ goto out;
+
+ v = bus_space_read_4(sc->sc_bst, sc->sc_bsh, MDIOUSERACCESS0);
+ if ((v & (1 << 29)) == 0)
+out:
+ printf("%s error\n", __func__);
+
+}
+
+void
+cpsw_mii_statchg(struct device *self)
+{
+ return;
+}
+
+int
+cpsw_new_rxbuf(struct cpsw_softc * const sc, const u_int i)
+{
+ struct cpsw_ring_data * const rdp = sc->sc_rdp;
+ const u_int h = RXDESC_PREV(i);
+ struct cpsw_cpdma_bd bd;
+ struct mbuf *m;
+ int error = ENOBUFS;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+ goto reuse;
+ }
+
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
+ goto reuse;
+ }
+
+ /* We have a new buffer, prepare it for the ring. */
+
+ if (rdp->rx_mb[i] != NULL)
+ bus_dmamap_unload(sc->sc_bdt, rdp->rx_dm[i]);
+
+ m->m_len = m->m_pkthdr.len = MCLBYTES;
+
+ rdp->rx_mb[i] = m;
+
+ error = bus_dmamap_load_mbuf(sc->sc_bdt, rdp->rx_dm[i], rdp->rx_mb[i],
+ BUS_DMA_READ|BUS_DMA_NOWAIT);
+ if (error) {
+ printf("can't load rx DMA map %d: %d\n", i, error);
+ }
+
+ bus_dmamap_sync(sc->sc_bdt, rdp->rx_dm[i],
+ 0, rdp->rx_dm[i]->dm_mapsize, BUS_DMASYNC_PREREAD);
+
+ error = 0;
+
+reuse:
+ /* (re-)setup the descriptor */
+ bd.next = 0;
+ bd.bufptr = rdp->rx_dm[i]->dm_segs[0].ds_addr;
+ bd.bufoff = 0;
+ bd.buflen = MIN(0x7ff, rdp->rx_dm[i]->dm_segs[0].ds_len);
+ bd.pktlen = 0;
+ bd.flags = CPDMA_BD_OWNER;
+
+ cpsw_set_rxdesc(sc, i, &bd);
+ /* and link onto ring */
+ cpsw_set_rxdesc_next(sc, h, cpsw_rxdesc_paddr(sc, i));
+
+ return error;
+}
+
+int
+cpsw_init(struct ifnet *ifp)
+{
+ struct cpsw_softc * const sc = ifp->if_softc;
+ struct arpcom *ac = &sc->sc_ac;
+ struct mii_data * const mii = &sc->sc_mii;
+ int i;
+
+ cpsw_stop(ifp);
+
+ sc->sc_txnext = 0;
+ sc->sc_txhead = 0;
+
+ /* Reset wrapper */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET, 1);
+ while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET) & 1);
+
+ /* Reset SS */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET, 1);
+ while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET) & 1);
+
+ /* Clear table (30) and enable ALE(31) and set passthrough (4) */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_CONTROL, (3 << 30) | 0x10);
+
+ /* Reset and init Sliver port 1 and 2 */
+ for (i = 0; i < 2; i++) {
+ /* Reset */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i), 1);
+ while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i)) & 1);
+ /* Set Slave Mapping */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_RX_PRI_MAP(i), 0x76543210);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_TX_PRI_MAP(i+1), 0x33221100);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_RX_MAXLEN(i), 0x5f2);
+ /* Set MAC Address */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_SA_HI(i+1),
+ ac->ac_enaddr[0] | (ac->ac_enaddr[1] << 8) |
+ (ac->ac_enaddr[2] << 16) | (ac->ac_enaddr[3] << 24));
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P_SA_LO(i+1),
+ ac->ac_enaddr[4] | (ac->ac_enaddr[5] << 8));
+
+ /* Set MACCONTROL for ports 0,1: FULLDUPLEX(0), GMII_EN(5),
+ IFCTL_A(15), IFCTL_B(16) FIXME */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_MACCONTROL(i),
+ 1 | (1<<5) | (1<<15) | (1<<16));
+
+ /* Set ALE port to forwarding(3) on the active port */
+ if (i == sc->sc_active_port)
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_PORTCTL(i+1), 3);
+ }
+
+ /* Set Host Port Mapping */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
+
+ /* Set ALE port to forwarding(3) */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_ALE_PORTCTL(0), 3);
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_PTYPE, 0);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_STAT_PORT_EN, 7);
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET, 1);
+ while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET) & 1);
+
+ for (i = 0; i < 8; i++) {
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(i), 0);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(i), 0);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(i), 0);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CP(i), 0);
+ }
+
+ bus_space_set_region_4(sc->sc_bst, sc->sc_bsh_txdescs, 0, 0,
+ CPSW_CPPI_RAM_TXDESCS_SIZE/4);
+
+ sc->sc_txhead = 0;
+ sc->sc_txnext = 0;
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_FREEBUFFER(0), 0);
+
+ bus_space_set_region_4(sc->sc_bst, sc->sc_bsh_rxdescs, 0, 0,
+ CPSW_CPPI_RAM_RXDESCS_SIZE/4);
+
+ /* Initialize RX Buffer Descriptors */
+ cpsw_set_rxdesc_next(sc, RXDESC_PREV(0), 0);
+ for (i = 0; i < CPSW_NRXDESCS; i++) {
+ cpsw_new_rxbuf(sc, i);
+ }
+ sc->sc_rxhead = 0;
+
+ /* align layer 3 header to 32-bit */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_BUFFER_OFFSET, ETHER_ALIGN);
+
+ /* Clear all interrupt Masks */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
+
+ /* Enable TX & RX DMA */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CONTROL, 1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CONTROL, 1);
+
+ /* Enable interrupt pacing for C0 RX/TX (IMAX set to max intr/ms allowed) */
+#define CPSW_VBUSP_CLK_MHZ 2400 /* hardcoded for BBB */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_RX_IMAX(0), 2);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_TX_IMAX(0), 2);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_INT_CONTROL, 3 << 16 | CPSW_VBUSP_CLK_MHZ/4);
+
+ /* Enable TX and RX interrupt receive for core 0 */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_TX_EN(0), 1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_RX_EN(0), 1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_MISC_EN(0), 0x1F);
+
+ /* Enable host Error Interrupt */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMA_INTMASK_SET, 2);
+
+ /* Enable interrupts for TX and RX Channel 0 */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_INTMASK_SET, 1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_INTMASK_SET, 1);
+
+ /* Ack stalled irqs */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_RXTH);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_RX);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_TX);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_MISC);
+
+ cpsw_mdio_init(sc);
+
+ mii_mediachg(mii);
+
+ /* Write channel 0 RX HDP */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(0), cpsw_rxdesc_paddr(sc, 0));
+ sc->sc_rxrun = true;
+ sc->sc_rxeoq = false;
+
+ sc->sc_txrun = true;
+ sc->sc_txeoq = true;
+
+ ifp->if_flags |= IFF_RUNNING;
+ ifq_clr_oactive(&ifp->if_snd);
+
+ timeout_add_sec(&sc->sc_tick, 1);
+
+ return 0;
+}
+
+void
+cpsw_stop(struct ifnet *ifp)
+{
+ struct cpsw_softc * const sc = ifp->if_softc;
+ struct cpsw_ring_data * const rdp = sc->sc_rdp;
+ u_int i;
+
+#if 0
+ /* XXX find where disable comes from */
+ printf("%s: ifp %p disable %d\n", __func__, ifp, disable);
+#endif
+ if ((ifp->if_flags & IFF_RUNNING) == 0)
+ return;
+
+ timeout_del(&sc->sc_tick);
+
+ mii_down(&sc->sc_mii);
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_INTMASK_CLEAR, 1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_INTMASK_CLEAR, 1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_TX_EN(0), 0x0);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_RX_EN(0), 0x0);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_MISC_EN(0), 0x1F);
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_TEARDOWN, 0);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_TEARDOWN, 0);
+ i = 0;
+ while ((sc->sc_txrun || sc->sc_rxrun) && i < 10000) {
+ delay(10);
+ if ((sc->sc_txrun == true) && cpsw_txintr(sc) == 0)
+ sc->sc_txrun = false;
+ if ((sc->sc_rxrun == true) && cpsw_rxintr(sc) == 0)
+ sc->sc_rxrun = false;
+ i++;
+ }
+ /* printf("%s toredown complete in %u\n", __func__, i); */
+
+ /* Reset wrapper */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET, 1);
+ while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_SOFT_RESET) & 1);
+
+ /* Reset SS */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET, 1);
+ while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_SOFT_RESET) & 1);
+
+ for (i = 0; i < 2; i++) {
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i), 1);
+ while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SL_SOFT_RESET(i)) & 1);
+ }
+
+ /* Reset CPDMA */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET, 1);
+ while(bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_SOFT_RESET) & 1);
+
+ /* Release any queued transmit buffers. */
+ for (i = 0; i < CPSW_NTXDESCS; i++) {
+ bus_dmamap_unload(sc->sc_bdt, rdp->tx_dm[i]);
+ m_freem(rdp->tx_mb[i]);
+ rdp->tx_mb[i] = NULL;
+ }
+
+ ifp->if_flags &= ~IFF_RUNNING;
+ ifp->if_timer = 0;
+ ifq_clr_oactive(&ifp->if_snd);
+
+ /* XXX Not sure what this is doing calling disable here
+ where is disable set?
+ */
+#if 0
+ if (!disable)
+ return;
+#endif
+
+ for (i = 0; i < CPSW_NRXDESCS; i++) {
+ bus_dmamap_unload(sc->sc_bdt, rdp->rx_dm[i]);
+ m_freem(rdp->rx_mb[i]);
+ rdp->rx_mb[i] = NULL;
+ }
+}
+
+int
+cpsw_rxthintr(void *arg)
+{
+ struct cpsw_softc * const sc = arg;
+
+ /* this won't deassert the interrupt though */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_RXTH);
+
+ return 1;
+}
+
+int
+cpsw_rxintr(void *arg)
+{
+ struct cpsw_softc * const sc = arg;
+ struct ifnet * const ifp = &sc->sc_ac.ac_if;
+ struct cpsw_ring_data * const rdp = sc->sc_rdp;
+ struct cpsw_cpdma_bd bd;
+ bus_dmamap_t dm;
+ struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+ struct mbuf *m;
+ u_int i;
+ u_int len, off;
+
+ sc->sc_rxeoq = false;
+
+ for (;;) {
+ KASSERT(sc->sc_rxhead < CPSW_NRXDESCS);
+
+ i = sc->sc_rxhead;
+ dm = rdp->rx_dm[i];
+ m = rdp->rx_mb[i];
+
+ KASSERT(dm != NULL);
+ KASSERT(m != NULL);
+
+ cpsw_get_rxdesc(sc, i, &bd);
+
+ if (bd.flags & CPDMA_BD_OWNER)
+ break;
+
+ if (bd.flags & CPDMA_BD_TDOWNCMPLT) {
+ sc->sc_rxrun = false;
+ goto done;
+ }
+
+ bus_dmamap_sync(sc->sc_bdt, dm, 0, dm->dm_mapsize,
+ BUS_DMASYNC_POSTREAD);
+
+ if (cpsw_new_rxbuf(sc, i) != 0) {
+ /* drop current packet, reuse buffer for new */
+ ifp->if_ierrors++;
+ goto next;
+ }
+
+ if ((bd.flags & (CPDMA_BD_SOP|CPDMA_BD_EOP)) !=
+ (CPDMA_BD_SOP|CPDMA_BD_EOP)) {
+ if (bd.flags & CPDMA_BD_SOP) {
+ printf("cpsw: rx packet too large\n");
+ ifp->if_ierrors++;
+ }
+ m_freem(m);
+ goto next;
+ }
+
+ off = bd.bufoff;
+ len = bd.pktlen;
+
+ if (bd.flags & CPDMA_BD_PASSCRC)
+ len -= ETHER_CRC_LEN;
+
+ m->m_pkthdr.len = m->m_len = len;
+ m->m_data += off;
+
+ ml_enqueue(&ml, m);
+
+next:
+ sc->sc_rxhead = RXDESC_NEXT(sc->sc_rxhead);
+ if (bd.flags & CPDMA_BD_EOQ) {
+ sc->sc_rxeoq = true;
+ sc->sc_rxrun = false;
+ }
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CP(0),
+ cpsw_rxdesc_paddr(sc, i));
+ }
+
+ if (sc->sc_rxeoq) {
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(0),
+ cpsw_rxdesc_paddr(sc, sc->sc_rxhead));
+ sc->sc_rxrun = true;
+ sc->sc_rxeoq = false;
+ }
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR,
+ CPSW_INTROFF_RX);
+
+done:
+ if_input(ifp, &ml);
+
+ return 1;
+}
+
+void
+cpsw_tick(void *arg)
+{
+ struct cpsw_softc *sc = arg;
+ int s;
+
+ s = splnet();
+ mii_tick(&sc->sc_mii);
+ splx(s);
+
+ timeout_add_sec(&sc->sc_tick, 1);
+}
+
+int
+cpsw_txintr(void *arg)
+{
+ struct cpsw_softc * const sc = arg;
+ struct ifnet * const ifp = &sc->sc_ac.ac_if;
+ struct cpsw_ring_data * const rdp = sc->sc_rdp;
+ struct cpsw_cpdma_bd bd;
+ bool handled = false;
+ uint32_t tx0_cp;
+ u_int cpi;
+
+ KASSERT(sc->sc_txrun);
+
+ tx0_cp = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0));
+
+ if (tx0_cp == 0xfffffffc) {
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0), 0xfffffffc);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0), 0);
+ sc->sc_txrun = false;
+ return 0;
+ }
+
+ for (;;) {
+ tx0_cp = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0));
+ cpi = (tx0_cp - sc->sc_txdescs_pa) /
+ sizeof(struct cpsw_cpdma_bd);
+ KASSERT(sc->sc_txhead < CPSW_NTXDESCS);
+
+ cpsw_get_txdesc(sc, sc->sc_txhead, &bd);
+
+ if (bd.buflen == 0) {
+ /* Debugger(); */
+ }
+
+ if ((bd.flags & CPDMA_BD_SOP) == 0)
+ goto next;
+
+ if (bd.flags & CPDMA_BD_OWNER) {
+ printf("pwned %x %x %x\n", cpi, sc->sc_txhead,
+ sc->sc_txnext);
+ break;
+ }
+
+ if (bd.flags & CPDMA_BD_TDOWNCMPLT) {
+ sc->sc_txrun = false;
+ return 1;
+ }
+
+ bus_dmamap_sync(sc->sc_bdt, rdp->tx_dm[sc->sc_txhead],
+ 0, rdp->tx_dm[sc->sc_txhead]->dm_mapsize,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_bdt, rdp->tx_dm[sc->sc_txhead]);
+
+ m_freem(rdp->tx_mb[sc->sc_txhead]);
+ rdp->tx_mb[sc->sc_txhead] = NULL;
+
+ ifp->if_opackets++;
+
+ handled = true;
+
+ ifq_clr_oactive(&ifp->if_snd);
+
+next:
+ if ((bd.flags & (CPDMA_BD_EOP|CPDMA_BD_EOQ)) ==
+ (CPDMA_BD_EOP|CPDMA_BD_EOQ))
+ sc->sc_txeoq = true;
+
+ if (sc->sc_txhead == cpi) {
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0),
+ cpsw_txdesc_paddr(sc, cpi));
+ sc->sc_txhead = TXDESC_NEXT(sc->sc_txhead);
+ break;
+ }
+ sc->sc_txhead = TXDESC_NEXT(sc->sc_txhead);
+ if (sc->sc_txeoq == true)
+ break;
+ }
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_TX);
+
+ if ((sc->sc_txnext != sc->sc_txhead) && sc->sc_txeoq) {
+ if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0)) == 0) {
+ sc->sc_txeoq = false;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0),
+ cpsw_txdesc_paddr(sc, sc->sc_txhead));
+ }
+ }
+
+ if (handled && sc->sc_txnext == sc->sc_txhead)
+ ifp->if_timer = 0;
+
+ if (handled)
+ cpsw_start(ifp);
+
+ return handled;
+}
+
+int
+cpsw_miscintr(void *arg)
+{
+ struct cpsw_softc * const sc = arg;
+ uint32_t miscstat;
+ uint32_t dmastat;
+ uint32_t stat;
+
+ miscstat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_WR_C_MISC_STAT(0));
+ printf("%s %x FIRE\n", __func__, miscstat);
+
+ if (miscstat & CPSW_MISC_HOST_PEND) {
+ /* Host Error */
+ dmastat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMA_INTSTAT_MASKED);
+ printf("CPSW_CPDMA_DMA_INTSTAT_MASKED %x\n", dmastat);
+
+ printf("rxhead %02x\n", sc->sc_rxhead);
+
+ stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMASTATUS);
+ printf("CPSW_CPDMA_DMASTATUS %x\n", stat);
+ stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_HDP(0));
+ printf("CPSW_CPDMA_TX0_HDP %x\n", stat);
+ stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_TX_CP(0));
+ printf("CPSW_CPDMA_TX0_CP %x\n", stat);
+ stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(0));
+ printf("CPSW_CPDMA_RX0_HDP %x\n", stat);
+ stat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CP(0));
+ printf("CPSW_CPDMA_RX0_CP %x\n", stat);
+
+ /* Debugger(); */
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMA_INTMASK_CLEAR, dmastat);
+ dmastat = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_DMA_INTSTAT_MASKED);
+ printf("CPSW_CPDMA_DMA_INTSTAT_MASKED %x\n", dmastat);
+ }
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, CPSW_INTROFF_MISC);
+
+ return 1;
+}
--- /dev/null
+/* $OpenBSD: if_cpswreg.h,v 1.6 2016/03/02 01:31:41 canacar Exp $ */
+
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
+ * 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 _IF_CPSWREG_H
+#define _IF_CPSWREG_H
+
+#define CPSW_SS_OFFSET 0x0000
+#define CPSW_SS_IDVER (CPSW_SS_OFFSET + 0x00)
+#define CPSW_SS_IDVER_RTL(_r) (((_r) >> 11) & 0x1f)
+#define CPSW_SS_IDVER_MAJ(_r) (((_r) >> 8) & 0x7)
+#define CPSW_SS_IDVER_MIN(_r) ((_r) & 0xff)
+#define CPSW_SS_SOFT_RESET (CPSW_SS_OFFSET + 0x08)
+#define CPSW_SS_STAT_PORT_EN (CPSW_SS_OFFSET + 0x0C)
+#define CPSW_SS_PTYPE (CPSW_SS_OFFSET + 0x10)
+
+#define CPSW_PORT_OFFSET 0x0100
+#define CPSW_PORT_P_TX_PRI_MAP(p) (CPSW_PORT_OFFSET + 0x118 + ((p-1) * 0x100))
+#define CPSW_PORT_P0_CPDMA_TX_PRI_MAP (CPSW_PORT_OFFSET + 0x01C)
+#define CPSW_PORT_P0_CPDMA_RX_CH_MAP (CPSW_PORT_OFFSET + 0x020)
+#define CPSW_PORT_P_SA_LO(p) (CPSW_PORT_OFFSET + 0x120 + ((p-1) * 0x100))
+#define CPSW_PORT_P_SA_HI(p) (CPSW_PORT_OFFSET + 0x124 + ((p-1) * 0x100))
+
+#define CPSW_CPDMA_OFFSET 0x0800
+#define CPSW_CPDMA_TX_CONTROL (CPSW_CPDMA_OFFSET + 0x04)
+#define CPSW_CPDMA_TX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x08)
+#define CPSW_CPDMA_RX_CONTROL (CPSW_CPDMA_OFFSET + 0x14)
+#define CPSW_CPDMA_RX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x18)
+#define CPSW_CPDMA_SOFT_RESET (CPSW_CPDMA_OFFSET + 0x1c)
+#define CPSW_CPDMA_DMACONTROL (CPSW_CPDMA_OFFSET + 0x20)
+#define CPSW_CPDMA_DMASTATUS (CPSW_CPDMA_OFFSET + 0x24)
+#define CPSW_CPDMA_RX_BUFFER_OFFSET (CPSW_CPDMA_OFFSET + 0x28)
+#define CPSW_CPDMA_TX_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0x80)
+#define CPSW_CPDMA_TX_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0x84)
+#define CPSW_CPDMA_TX_INTMASK_SET (CPSW_CPDMA_OFFSET + 0x88)
+#define CPSW_CPDMA_TX_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0x8C)
+#define CPSW_CPDMA_CPDMA_EOI_VECTOR (CPSW_CPDMA_OFFSET + 0x94)
+#define CPSW_CPDMA_RX_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0xA0)
+#define CPSW_CPDMA_RX_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0xA4)
+#define CPSW_CPDMA_RX_INTMASK_SET (CPSW_CPDMA_OFFSET + 0xA8)
+#define CPSW_CPDMA_RX_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0xAc)
+#define CPSW_CPDMA_DMA_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0xB0)
+#define CPSW_CPDMA_DMA_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0xB4)
+#define CPSW_CPDMA_DMA_INTMASK_SET (CPSW_CPDMA_OFFSET + 0xB8)
+#define CPSW_CPDMA_DMA_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0xBC)
+#define CPSW_CPDMA_RX_FREEBUFFER(p) (CPSW_CPDMA_OFFSET + 0x0e0 + ((p) * 0x04))
+
+#define CPSW_STATS_OFFSET 0x0900
+
+#define CPSW_STATERAM_OFFSET 0x0A00
+#define CPSW_CPDMA_TX_HDP(p) (CPSW_STATERAM_OFFSET + 0x00 + ((p) * 0x04))
+#define CPSW_CPDMA_RX_HDP(p) (CPSW_STATERAM_OFFSET + 0x20 + ((p) * 0x04))
+#define CPSW_CPDMA_TX_CP(p) (CPSW_STATERAM_OFFSET + 0x40 + ((p) * 0x04))
+#define CPSW_CPDMA_RX_CP(p) (CPSW_STATERAM_OFFSET + 0x60 + ((p) * 0x04))
+
+#define CPSW_CPTS_OFFSET 0x0C00
+
+#define CPSW_ALE_OFFSET 0x0D00
+#define CPSW_ALE_CONTROL (CPSW_ALE_OFFSET + 0x08)
+#define CPSW_ALE_TBLCTL (CPSW_ALE_OFFSET + 0x20)
+#define CPSW_ALE_TBLW2 (CPSW_ALE_OFFSET + 0x34)
+#define CPSW_ALE_TBLW1 (CPSW_ALE_OFFSET + 0x38)
+#define CPSW_ALE_TBLW0 (CPSW_ALE_OFFSET + 0x3C)
+#define CPSW_ALE_PORTCTL(p) (CPSW_ALE_OFFSET + 0x40 + ((p) * 0x04))
+
+#define CPSW_SL_OFFSET 0x0D80
+#define CPSW_SL_MACCONTROL(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x04)
+#define CPSW_SL_SOFT_RESET(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x0C)
+#define CPSW_SL_RX_MAXLEN(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x10)
+#define CPSW_SL_RX_PRI_MAP(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x24)
+
+#define MDIO_OFFSET 0x1000
+#define MDIOCONTROL (MDIO_OFFSET + 0x04)
+#define MDIOALIVE (MDIO_OFFSET + 0x08)
+#define MDIOLINK (MDIO_OFFSET + 0x0C)
+#define MDIOUSERACCESS0 (MDIO_OFFSET + 0x80)
+#define MDIOUSERPHYSEL0 (MDIO_OFFSET + 0x84)
+
+#define CPSW_WR_OFFSET 0x1200
+#define CPSW_WR_SOFT_RESET (CPSW_WR_OFFSET + 0x04)
+#define CPSW_WR_CONTROL (CPSW_WR_OFFSET + 0x08)
+#define CPSW_WR_INT_CONTROL (CPSW_WR_OFFSET + 0x0c)
+#define CPSW_WR_C_RX_THRESH_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x10)
+#define CPSW_WR_C_RX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x14)
+#define CPSW_WR_C_TX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x18)
+#define CPSW_WR_C_MISC_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x1C)
+#define CPSW_WR_C_RX_THRESH_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x40)
+#define CPSW_WR_C_RX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x44)
+#define CPSW_WR_C_TX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x48)
+#define CPSW_WR_C_MISC_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x4C)
+#define CPSW_WR_C_RX_IMAX(p) (CPSW_WR_OFFSET + (0x08 * (p)) + 0x70)
+#define CPSW_WR_C_TX_IMAX(p) (CPSW_WR_OFFSET + (0x08 * (p)) + 0x74)
+#define CPSW_MISC_HOST_PEND 0x0004
+
+#define CPSW_CPPI_RAM_OFFSET 0x2000
+
+#define CPDMA_BD_SOP (1<<15)
+#define CPDMA_BD_EOP (1<<14)
+#define CPDMA_BD_OWNER (1<<13)
+#define CPDMA_BD_EOQ (1<<12)
+#define CPDMA_BD_TDOWNCMPLT (1<<11)
+#define CPDMA_BD_PASSCRC (1<<10)
+#define CPDMA_BD_PKT_ERR_MASK (3<< 4)
+
+struct cpsw_cpdma_bd {
+ uint32_t next;
+ uint32_t bufptr;
+ uint16_t buflen;
+ uint16_t bufoff;
+ uint16_t pktlen;
+ uint16_t flags;
+};
+
+/* Interrupt offsets */
+#define CPSW_INTROFF_RXTH 0
+#define CPSW_INTROFF_RX 1
+#define CPSW_INTROFF_TX 2
+#define CPSW_INTROFF_MISC 3
+
+#endif /*_IF_CPSWREG_H */
--- /dev/null
+/* $OpenBSD: intc.c,v 1.4 2016/01/31 00:14:50 jsg Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/evcount.h>
+#include <machine/bus.h>
+#include <armv7/armv7/armv7var.h>
+#include "intc.h"
+
+#define INTC_NUM_IRQ intc_nirq
+#define INTC_NUM_BANKS (intc_nirq/32)
+#define INTC_MAX_IRQ 128
+#define INTC_MAX_BANKS (INTC_MAX_IRQ/32)
+
+/* registers */
+#define INTC_REVISION 0x00 /* R */
+#define INTC_SYSCONFIG 0x10 /* RW */
+#define INTC_SYSCONFIG_AUTOIDLE 0x1
+#define INTC_SYSCONFIG_SOFTRESET 0x2
+#define INTC_SYSSTATUS 0x14 /* R */
+#define INTC_SYSSYSTATUS_RESETDONE 0x1
+#define INTC_SIR_IRQ 0x40 /* R */
+#define INTC_SIR_FIQ 0x44 /* R */
+#define INTC_CONTROL 0x48 /* RW */
+#define INTC_CONTROL_NEWIRQ 0x1
+#define INTC_CONTROL_NEWFIQ 0x2
+#define INTC_CONTROL_GLOBALMASK 0x1
+#define INTC_PROTECTION 0x4c /* RW */
+#define INTC_PROTECTION_PROT 1 /* only privileged mode */
+#define INTC_IDLE 0x50 /* RW */
+
+#define INTC_IRQ_TO_REG(i) (((i) >> 5) & 0x3)
+#define INTC_IRQ_TO_REGi(i) ((i) & 0x1f)
+#define INTC_ITRn(i) 0x80+(0x20*i)+0x00 /* R */
+#define INTC_MIRn(i) 0x80+(0x20*i)+0x04 /* RW */
+#define INTC_CLEARn(i) 0x80+(0x20*i)+0x08 /* RW */
+#define INTC_SETn(i) 0x80+(0x20*i)+0x0c /* RW */
+#define INTC_ISR_SETn(i) 0x80+(0x20*i)+0x10 /* RW */
+#define INTC_ISR_CLEARn(i) 0x80+(0x20*i)+0x14 /* RW */
+#define INTC_PENDING_IRQn(i) 0x80+(0x20*i)+0x18 /* R */
+#define INTC_PENDING_FIQn(i) 0x80+(0x20*i)+0x1c /* R */
+
+#define INTC_ILRn(i) 0x100+(4*i)
+#define INTC_ILR_IRQ 0x0 /* not of FIQ */
+#define INTC_ILR_FIQ 0x1
+#define INTC_ILR_PRIs(pri) ((pri) << 2)
+#define INTC_ILR_PRI(reg) (((reg) >> 2) & 0x2f)
+#define INTC_MIN_PRI 63
+#define INTC_STD_PRI 32
+#define INTC_MAX_PRI 0
+
+struct intrhand {
+ TAILQ_ENTRY(intrhand) ih_list; /* link on intrq list */
+ int (*ih_func)(void *); /* handler */
+ void *ih_arg; /* arg for handler */
+ int ih_ipl; /* IPL_* */
+ int ih_irq; /* IRQ number */
+ struct evcount ih_count;
+ char *ih_name;
+};
+
+struct intrq {
+ TAILQ_HEAD(, intrhand) iq_list; /* handler list */
+ int iq_irq; /* IRQ to mask while handling */
+ int iq_levels; /* IPL_*'s this IRQ has */
+ int iq_ist; /* share type */
+};
+
+volatile int softint_pending;
+
+struct intrq intc_handler[INTC_MAX_IRQ];
+u_int32_t intc_smask[NIPL];
+u_int32_t intc_imask[INTC_MAX_BANKS][NIPL];
+
+bus_space_tag_t intc_iot;
+bus_space_handle_t intc_ioh;
+int intc_nirq;
+
+void intc_attach(struct device *, struct device *, void *);
+int intc_spllower(int new);
+int intc_splraise(int new);
+void intc_setipl(int new);
+void intc_calc_mask(void);
+
+struct cfattach intc_ca = {
+ sizeof (struct device), NULL, intc_attach
+};
+
+struct cfdriver intc_cd = {
+ NULL, "intc", DV_DULL
+};
+
+int intc_attached = 0;
+
+void
+intc_attach(struct device *parent, struct device *self, void *args)
+{
+ struct armv7_attach_args *aa = args;
+ int i;
+ u_int32_t rev;
+
+ intc_iot = aa->aa_iot;
+ if (bus_space_map(intc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &intc_ioh))
+ panic("intc_attach: bus_space_map failed!");
+
+ rev = bus_space_read_4(intc_iot, intc_ioh, INTC_REVISION);
+
+ printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
+
+ /* software reset of the part? */
+ /* set protection bit (kernel only)? */
+#if 0
+ bus_space_write_4(intc_iot, intc_ioh, INTC_PROTECTION,
+ INTC_PROTECTION_PROT);
+#endif
+
+ /* enable interface clock power saving mode */
+ bus_space_write_4(intc_iot, intc_ioh, INTC_SYSCONFIG,
+ INTC_SYSCONFIG_AUTOIDLE);
+
+ switch (board_id) {
+ case BOARD_ID_AM335X_BEAGLEBONE:
+ intc_nirq = 128;
+ break;
+ default:
+ intc_nirq = 96;
+ break;
+ }
+
+ /* mask all interrupts */
+ for (i = 0; i < INTC_NUM_BANKS; i++)
+ bus_space_write_4(intc_iot, intc_ioh, INTC_MIRn(i), 0xffffffff);
+
+ for (i = 0; i < INTC_NUM_IRQ; i++) {
+ bus_space_write_4(intc_iot, intc_ioh, INTC_ILRn(i),
+ INTC_ILR_PRIs(INTC_MIN_PRI)|INTC_ILR_IRQ);
+
+ TAILQ_INIT(&intc_handler[i].iq_list);
+ }
+
+ intc_calc_mask();
+ bus_space_write_4(intc_iot, intc_ioh, INTC_CONTROL,
+ INTC_CONTROL_NEWIRQ);
+
+ intc_attached = 1;
+
+ /* insert self as interrupt handler */
+ arm_set_intr_handler(intc_splraise, intc_spllower, intc_splx,
+ intc_setipl,
+ intc_intr_establish, intc_intr_disestablish, intc_intr_string,
+ intc_irq_handler);
+
+ intc_setipl(IPL_HIGH); /* XXX ??? */
+ enable_interrupts(PSR_I);
+}
+
+void
+intc_calc_mask(void)
+{
+ struct cpu_info *ci = curcpu();
+ int irq;
+ struct intrhand *ih;
+ int i;
+
+ for (irq = 0; irq < INTC_NUM_IRQ; irq++) {
+ int max = IPL_NONE;
+ int min = IPL_HIGH;
+ TAILQ_FOREACH(ih, &intc_handler[irq].iq_list, ih_list) {
+ if (ih->ih_ipl > max)
+ max = ih->ih_ipl;
+
+ if (ih->ih_ipl < min)
+ min = ih->ih_ipl;
+ }
+
+ intc_handler[irq].iq_irq = max;
+
+ if (max == IPL_NONE)
+ min = IPL_NONE;
+
+#ifdef DEBUG_INTC
+ if (min != IPL_NONE) {
+ printf("irq %d to block at %d %d reg %d bit %d\n",
+ irq, max, min, INTC_IRQ_TO_REG(irq),
+ INTC_IRQ_TO_REGi(irq));
+ }
+#endif
+ /* Enable interrupts at lower levels, clear -> enable */
+ for (i = 0; i < min; i++)
+ intc_imask[INTC_IRQ_TO_REG(irq)][i] &=
+ ~(1 << INTC_IRQ_TO_REGi(irq));
+ for (; i <= IPL_HIGH; i++)
+ intc_imask[INTC_IRQ_TO_REG(irq)][i] |=
+ 1 << INTC_IRQ_TO_REGi(irq);
+ /* XXX - set enable/disable, priority */
+ bus_space_write_4(intc_iot, intc_ioh, INTC_ILRn(irq),
+ INTC_ILR_PRIs(NIPL-max)|INTC_ILR_IRQ);
+ }
+ arm_init_smask();
+ intc_setipl(ci->ci_cpl);
+}
+
+void
+intc_splx(int new)
+{
+ struct cpu_info *ci = curcpu();
+ intc_setipl(new);
+
+ if (ci->ci_ipending & arm_smask[ci->ci_cpl])
+ arm_do_pending_intr(ci->ci_cpl);
+}
+
+int
+intc_spllower(int new)
+{
+ struct cpu_info *ci = curcpu();
+ int old = ci->ci_cpl;
+ intc_splx(new);
+ return (old);
+}
+
+int
+intc_splraise(int new)
+{
+ struct cpu_info *ci = curcpu();
+ int old;
+ old = ci->ci_cpl;
+
+ /*
+ * setipl must always be called because there is a race window
+ * where the variable is updated before the mask is set
+ * an interrupt occurs in that window without the mask always
+ * being set, the hardware might not get updated on the next
+ * splraise completely messing up spl protection.
+ */
+ if (old > new)
+ new = old;
+
+ intc_setipl(new);
+
+ return (old);
+}
+
+void
+intc_setipl(int new)
+{
+ struct cpu_info *ci = curcpu();
+ int i;
+ int psw;
+ if (intc_attached == 0)
+ return;
+
+ psw = disable_interrupts(PSR_I);
+#if 0
+ {
+ volatile static int recursed = 0;
+ if (recursed == 0) {
+ recursed = 1;
+ if (new != 12)
+ printf("setipl %d\n", new);
+ recursed = 0;
+ }
+ }
+#endif
+ ci->ci_cpl = new;
+ for (i = 0; i < INTC_NUM_BANKS; i++)
+ bus_space_write_4(intc_iot, intc_ioh,
+ INTC_MIRn(i), intc_imask[i][new]);
+ bus_space_write_4(intc_iot, intc_ioh, INTC_CONTROL,
+ INTC_CONTROL_NEWIRQ);
+ restore_interrupts(psw);
+}
+
+void
+intc_intr_bootstrap(vaddr_t addr)
+{
+ int i, j;
+ extern struct bus_space armv7_bs_tag;
+ intc_iot = &armv7_bs_tag;
+ intc_ioh = addr;
+ for (i = 0; i < INTC_NUM_BANKS; i++)
+ for (j = 0; j < NIPL; j++)
+ intc_imask[i][j] = 0xffffffff;
+}
+
+void
+intc_irq_handler(void *frame)
+{
+ int irq, pri, s;
+ struct intrhand *ih;
+ void *arg;
+
+ irq = bus_space_read_4(intc_iot, intc_ioh, INTC_SIR_IRQ);
+#ifdef DEBUG_INTC
+ printf("irq %d fired\n", irq);
+#endif
+
+ pri = intc_handler[irq].iq_irq;
+ s = intc_splraise(pri);
+ TAILQ_FOREACH(ih, &intc_handler[irq].iq_list, ih_list) {
+ if (ih->ih_arg != 0)
+ arg = ih->ih_arg;
+ else
+ arg = frame;
+
+ if (ih->ih_func(arg))
+ ih->ih_count.ec_count++;
+
+ }
+ bus_space_write_4(intc_iot, intc_ioh, INTC_CONTROL,
+ INTC_CONTROL_NEWIRQ);
+
+ intc_splx(s);
+}
+
+void *
+intc_intr_establish(int irqno, int level, int (*func)(void *),
+ void *arg, char *name)
+{
+ int psw;
+ struct intrhand *ih;
+
+ if (irqno < 0 || irqno >= INTC_NUM_IRQ)
+ panic("intc_intr_establish: bogus irqnumber %d: %s",
+ irqno, name);
+ psw = disable_interrupts(PSR_I);
+
+ /* no point in sleeping unless someone can free memory. */
+ ih = (struct intrhand *)malloc (sizeof *ih, M_DEVBUF,
+ cold ? M_NOWAIT : M_WAITOK);
+ if (ih == NULL)
+ panic("intr_establish: can't malloc handler info");
+ ih->ih_func = func;
+ ih->ih_arg = arg;
+ ih->ih_ipl = level;
+ ih->ih_irq = irqno;
+ ih->ih_name = name;
+
+ TAILQ_INSERT_TAIL(&intc_handler[irqno].iq_list, ih, ih_list);
+
+ if (name != NULL)
+ evcount_attach(&ih->ih_count, name, &ih->ih_irq);
+
+#ifdef DEBUG_INTC
+ printf("intc_intr_establish irq %d level %d [%s]\n", irqno, level,
+ name);
+#endif
+ intc_calc_mask();
+
+ restore_interrupts(psw);
+ return (ih);
+}
+
+void
+intc_intr_disestablish(void *cookie)
+{
+ int psw;
+ struct intrhand *ih = cookie;
+ int irqno = ih->ih_irq;
+ psw = disable_interrupts(PSR_I);
+ TAILQ_REMOVE(&intc_handler[irqno].iq_list, ih, ih_list);
+ if (ih->ih_name != NULL)
+ evcount_detach(&ih->ih_count);
+ free(ih, M_DEVBUF, 0);
+ restore_interrupts(psw);
+}
+
+const char *
+intc_intr_string(void *cookie)
+{
+ return "huh?";
+}
+
+
+#if 0
+int intc_tst(void *a);
+
+int
+intc_tst(void *a)
+{
+ printf("inct_tst called\n");
+ bus_space_write_4(intc_iot, intc_ioh, INTC_ISR_CLEARn(0), 2);
+ return 1;
+}
+
+void intc_test(void);
+void intc_test(void)
+{
+ void * ih;
+ printf("about to register handler\n");
+ ih = intc_intr_establish(1, IPL_BIO, intc_tst, NULL, "intctst");
+
+ printf("about to set bit\n");
+ bus_space_write_4(intc_iot, intc_ioh, INTC_ISR_SETn(0), 2);
+
+ printf("about to clear bit\n");
+ bus_space_write_4(intc_iot, intc_ioh, INTC_ISR_CLEARn(0), 2);
+
+ printf("about to remove handler\n");
+ intc_intr_disestablish(ih);
+
+ printf("done\n");
+}
+#endif
--- /dev/null
+/* $OpenBSD: intc.h,v 1.2 2014/03/29 18:09:28 guenther Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _OMAPINTC_INTR_H_
+#define _OMAPINTC_INTR_H_
+
+#ifndef _LOCORE
+
+#include <arm/armreg.h>
+#include <arm/cpufunc.h>
+#include <machine/intr.h>
+#include <arm/softintr.h>
+
+extern volatile int current_spl_level;
+extern volatile int softint_pending;
+void intc_do_pending(void);
+
+#define SI_TO_IRQBIT(si) (1U<<(si))
+void intc_setipl(int new);
+void intc_splx(int new);
+int intc_splraise(int ipl);
+int intc_spllower(int ipl);
+void intc_setsoftintr(int si);
+
+/*
+ * An useful function for interrupt handlers.
+ * XXX: This shouldn't be here.
+ */
+static __inline int
+find_first_bit( uint32_t bits )
+{
+ int count;
+
+ /* since CLZ is available only on ARMv5, this isn't portable
+ * to all ARM CPUs. This file is for OMAPINTC processor.
+ */
+ asm( "clz %0, %1" : "=r" (count) : "r" (bits) );
+ return 31-count;
+}
+
+
+/*
+ * This function *MUST* be called very early on in a port's
+ * initarm() function, before ANY spl*() functions are called.
+ *
+ * The parameter is the virtual address of the OMAPINTC's Interrupt
+ * Controller registers.
+ */
+void intc_intr_bootstrap(vaddr_t);
+
+void intc_irq_handler(void *);
+void *intc_intr_establish(int irqno, int level, int (*func)(void *),
+ void *cookie, char *name);
+void intc_intr_disestablish(void *cookie);
+const char *intc_intr_string(void *cookie);
+
+#endif /* ! _LOCORE */
+
+#endif /* _OMAPINTC_INTR_H_ */
+
--- /dev/null
+/* $OpenBSD: omap.c,v 1.9 2016/05/02 15:27:24 patrick Exp $ */
+/*
+ * Copyright (c) 2005,2008 Dale Rahn <drahn@openbsd.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <arm/mainbus/mainbus.h>
+#include <armv7/armv7/armv7var.h>
+
+int omap_match(struct device *, void *, void *);
+void omap3_init();
+void omap4_init();
+void am335x_init();
+
+struct cfattach omap_ca = {
+ sizeof(struct armv7_softc), omap_match, armv7_attach
+};
+
+struct cfdriver omap_cd = {
+ NULL, "omap", DV_DULL
+};
+
+struct board_dev beagleboard_devs[] = {
+ { "prcm", 0 },
+ { "intc", 0 },
+ { "gptimer", 0 },
+ { "gptimer", 1 },
+ { "omdog", 0 },
+ { "omgpio", 0 },
+ { "omgpio", 1 },
+ { "omgpio", 2 },
+ { "omgpio", 3 },
+ { "omgpio", 4 },
+ { "omgpio", 5 },
+ { "ommmc", 0 }, /* HSMMC1 */
+ { "com", 2 }, /* UART3 */
+ { NULL, 0 }
+};
+
+struct board_dev beaglebone_devs[] = {
+ { "prcm", 0 },
+ { "sitaracm", 0 },
+ { "intc", 0 },
+ { "edma", 0 },
+ { "dmtimer", 0 },
+ { "dmtimer", 1 },
+ { "omdog", 0 },
+ { "omgpio", 0 },
+ { "omgpio", 1 },
+ { "omgpio", 2 },
+ { "omgpio", 3 },
+ { "tiiic", 0 },
+ { "tiiic", 1 },
+ { "tiiic", 2 },
+ { "ommmc", 0 }, /* HSMMC0 */
+ { "ommmc", 1 }, /* HSMMC1 */
+ { "com", 0 }, /* UART0 */
+ { "cpsw", 0 },
+ { NULL, 0 }
+};
+
+struct board_dev overo_devs[] = {
+ { "prcm", 0 },
+ { "intc", 0 },
+ { "gptimer", 0 },
+ { "gptimer", 1 },
+ { "omdog", 0 },
+ { "omgpio", 0 },
+ { "omgpio", 1 },
+ { "omgpio", 2 },
+ { "omgpio", 3 },
+ { "omgpio", 4 },
+ { "omgpio", 5 },
+ { "ommmc", 0 }, /* HSMMC1 */
+ { "com", 2 }, /* UART3 */
+ { NULL, 0 }
+};
+
+struct board_dev pandaboard_devs[] = {
+ { "omapid", 0 },
+ { "prcm", 0 },
+ { "omdog", 0 },
+ { "omgpio", 0 },
+ { "omgpio", 1 },
+ { "omgpio", 2 },
+ { "omgpio", 3 },
+ { "omgpio", 4 },
+ { "omgpio", 5 },
+ { "ommmc", 0 }, /* HSMMC1 */
+ { "com", 2 }, /* UART3 */
+ { "ehci", 0 },
+ { NULL, 0 }
+};
+
+struct armv7_board omap_boards[] = {
+ {
+ BOARD_ID_OMAP3_BEAGLE,
+ "TI OMAP3 BeagleBoard",
+ beagleboard_devs,
+ omap3_init,
+ },
+ {
+ BOARD_ID_AM335X_BEAGLEBONE,
+ "TI AM335x BeagleBone",
+ beaglebone_devs,
+ am335x_init,
+ },
+ {
+ BOARD_ID_OMAP3_OVERO,
+ "Gumstix OMAP3 Overo",
+ overo_devs,
+ omap3_init,
+ },
+ {
+ BOARD_ID_OMAP4_PANDA,
+ "TI OMAP4 PandaBoard",
+ pandaboard_devs,
+ omap4_init,
+ },
+ { 0, NULL, NULL, NULL },
+};
+
+struct board_dev *
+omap_board_devs(void)
+{
+ int i;
+
+ for (i = 0; omap_boards[i].name != NULL; i++) {
+ if (omap_boards[i].board_id == board_id)
+ return (omap_boards[i].devs);
+ }
+ return (NULL);
+}
+
+void
+omap_board_init(void)
+{
+ int i;
+
+ for (i = 0; omap_boards[i].name != NULL; i++) {
+ if (omap_boards[i].board_id == board_id) {
+ omap_boards[i].init();
+ break;
+ }
+ }
+}
+
+const char *
+omap_board_name(void)
+{
+ int i;
+
+ for (i = 0; omap_boards[i].name != NULL; i++) {
+ if (omap_boards[i].board_id == board_id)
+ return (omap_boards[i].name);
+ }
+ return (NULL);
+}
+
+int
+omap_match(struct device *parent, void *cfdata, void *aux)
+{
+ union mainbus_attach_args *ma = (union mainbus_attach_args *)aux;
+ struct cfdata *cf = (struct cfdata *)cfdata;
+
+ if (ma->ma_name == NULL)
+ return (0);
+
+ if (strcmp(cf->cf_driver->cd_name, ma->ma_name) != 0)
+ return (0);
+
+ return (omap_board_devs() != NULL);
+}
--- /dev/null
+/* $OpenBSD: omap3.c,v 1.2 2013/11/06 19:03:07 syl Exp $ */
+
+/*
+ * Copyright (c) 2011 Uwe Stuehler <uwe@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <machine/bus.h>
+
+#include <armv7/armv7/armv7var.h>
+
+#define PRCM_ADDR 0x48004000
+#define PRCM_SIZE 0x2000
+
+#define INTC_ADDR 0x48200000
+#define INTC_SIZE 0x200
+
+#define GPTIMERx_SIZE 0x100
+#define GPTIMER1_ADDR 0x48318000
+#define GPTIMER1_IRQ 37
+#define GPTIMER2_ADDR 0x49032000
+#define GPTIMER2_IRQ 38
+
+#define WD_ADDR 0x48314000
+#define WD_SIZE 0x80
+
+#define GPIOx_SIZE 0x1000
+#define GPIO1_ADDR 0x48310000
+#define GPIO2_ADDR 0x49050000
+#define GPIO3_ADDR 0x49052000
+#define GPIO4_ADDR 0x49054000
+#define GPIO5_ADDR 0x49056000
+#define GPIO6_ADDR 0x49058000
+
+#define GPIO1_IRQ 29
+#define GPIO2_IRQ 30
+#define GPIO3_IRQ 31
+#define GPIO4_IRQ 32
+#define GPIO5_IRQ 33
+#define GPIO6_IRQ 34
+
+#define UARTx_SIZE 0x400
+#define UART1_ADDR 0x4806A000
+#define UART2_ADDR 0x4806C000
+#define UART3_ADDR 0x49020000
+
+#define UART1_IRQ 72
+#define UART2_IRQ 73
+#define UART3_IRQ 74
+
+#define HSMMCx_SIZE 0x200
+#define HSMMC1_ADDR 0x4809c000
+#define HSMMC1_IRQ 83
+
+#define USBTLL_ADDR 0x48062000
+#define USBTLL_SIZE 0x1000
+
+struct armv7_dev omap3_devs[] = {
+
+ /*
+ * Power, Reset and Clock Manager
+ */
+
+ { .name = "prcm",
+ .unit = 0,
+ .mem = { { PRCM_ADDR, PRCM_SIZE } },
+ },
+
+ /*
+ * Interrupt Controller
+ */
+
+ { .name = "intc",
+ .unit = 0,
+ .mem = { { INTC_ADDR, INTC_SIZE } },
+ },
+
+ /*
+ * General Purpose Timers
+ */
+
+ { .name = "gptimer",
+ .unit = 1, /* XXX see gptimer.c */
+ .mem = { { GPTIMER1_ADDR, GPTIMERx_SIZE } },
+ .irq = { GPTIMER1_IRQ }
+ },
+
+ { .name = "gptimer",
+ .unit = 0, /* XXX see gptimer.c */
+ .mem = { { GPTIMER2_ADDR, GPTIMERx_SIZE } },
+ .irq = { GPTIMER2_IRQ }
+ },
+
+ /*
+ * GPIO
+ */
+
+ { .name = "omgpio",
+ .unit = 0,
+ .mem = { { GPIO1_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO1_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 1,
+ .mem = { { GPIO2_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO2_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 2,
+ .mem = { { GPIO3_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO3_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 3,
+ .mem = { { GPIO4_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO4_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 4,
+ .mem = { { GPIO5_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO5_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 5,
+ .mem = { { GPIO6_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO6_IRQ }
+ },
+
+ /*
+ * Watchdog Timer
+ */
+
+ { .name = "omdog",
+ .unit = 0,
+ .mem = { { WD_ADDR, WD_SIZE } }
+ },
+
+ /*
+ * UART
+ */
+
+ { .name = "com",
+ .unit = 2,
+ .mem = { { UART3_ADDR, UARTx_SIZE } },
+ .irq = { UART3_IRQ }
+ },
+
+ /*
+ * MMC
+ */
+
+ { .name = "ommmc",
+ .unit = 0,
+ .mem = { { HSMMC1_ADDR, HSMMCx_SIZE } },
+ .irq = { HSMMC1_IRQ }
+ },
+
+ /*
+ * USB
+ */
+
+ { .name = "omusbtll",
+ .unit = 0,
+ .mem = { { USBTLL_ADDR, USBTLL_SIZE } },
+ },
+
+ /* Terminator */
+ { .name = NULL,
+ .unit = 0,
+ }
+};
+
+void
+omap3_init(void)
+{
+ armv7_set_devs(omap3_devs);
+}
--- /dev/null
+/* $OpenBSD: omap3_prcmreg.h,v 1.3 2013/10/28 11:11:50 rapha Exp $ */
+/*
+ * Copyright (c) 2007, 2009, 2012 Dale Rahn <drahn@dalerahn.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* XXX - verify these definitions and correctly merge them with omap4 */
+#define CM_FCLKEN_IVA2 0x0000
+#define CM_CLKEN_PLL_IVA2 0x0004
+#define CM_IDLEST_IVA2 0x0020
+#define CM_IDLEST_PLL_IVA2 0x0024
+#define CM_AUTOIDLE_PLL_IVA2 0x0034
+#define CM_CLKSEL1_PLL_IVA2 0x0040
+#define CM_CLKSEL2_PLL_IVA2 0x0044
+#define CM_CLKSTCTRL_IVA2 0x0048
+#define CM_CLKSTST_IVA2 0x004c
+#define CM_CLKSEL_MPU 0x0940
+#define CM_CLKSTCTRL_MPU 0x0948
+#define RM_RSTST_MPU 0x0958
+#define PM_WKDEP_MPU 0x09C8
+#define PM_EVGENCTRL_MPU 0x09D4
+#define PM_EVEGENONTIM_MPU 0x09D8
+#define PM_EVEGENOFFTIM_MPU 0x09DC
+#define PM_PWSTCTRL_MPU 0x09E0
+#define PM_PWSTST_MPU 0x09E4
+#define CM_FCLKEN1_CORE 0x0a00
+#define CM_FCLKEN1_CORE_MSK 0x41fffe00
+#define CM_FCLKEN2_CORE 0x0a04
+#define CM_FCLKEN2_CORE_MSK 0x00000000
+#define CM_FCLKEN3_CORE 0x0a08
+#define CM_FCLKEN3_CORE_MSK 0x00000007
+#define CM_ICLKEN1_CORE 0x0a10
+#define CM_ICLKEN1_CORE_MSK 0x7ffffed2
+#define CM_ICLKEN2_CORE 0x0a14
+#define CM_ICLKEN2_CORE_MSK 0x0000001f
+#define CM_ICLKEN3_CORE 0x0a18
+#define CM_ICLKEN3_CORE_MSK 0x00000004
+#define CM_ICLKEN4_CORE 0x0a1C
+#define CM_IDLEST1_CORE 0x0a20
+#define CM_IDLEST2_CORE 0x0a24
+#define CM_IDLEST4_CORE 0x0a2C
+#define CM_AUTOIDLE1_CORE 0x0a30
+#define CM_AUTOIDLE2_CORE 0x0a34
+#define CM_AUTOIDLE3_CORE 0x0a38
+#define CM_AUTOIDLE4_CORE 0x0a3C
+#define CM_CLKSEL1_CORE 0x0a40
+#define CM_CLKSEL2_CORE 0x0a44
+#define CM_CLKSTCTRL_CORE 0x0a48
+#define PM_WKEN1_CORE 0x0aA0
+#define PM_WKEN2_CORE 0x0aA4
+#define PM_WKST1_CORE 0x0aB0
+#define PM_WKST2_CORE 0x0aB4
+#define PM_WKDEP_CORE 0x0aC8
+#define PM_PWSTCTRL_CORE 0x0aE0
+#define PM_PWSTST_CORE 0x0aE4
+#define CM_FCLKEN_GFX 0x0b00
+#define CM_ICLKEN_GFX 0x0b10
+#define CM_IDLEST_GFX 0x0b20
+#define CM_CLKSEL_GFX 0x0b40
+#define CM_CLKSTCTRL_GFX 0x0b48
+#define RM_RSTCTRL_GFX 0x0b50
+#define RM_RSTST_GFX 0x0b58
+#define PM_WKDEP_GFX 0x0bC8
+#define PM_PWSTCTRL_GFX 0x0bE0
+#define PM_PWSTST_GFX 0x0bE4
+#define CM_FCLKEN_WKUP 0x0c00
+#define CM_FCLKEN_WKUP_MSK 0x00000029
+#define CM_ICLKEN_WKUP 0x0c10
+#define CM_ICLKEN_WKUP_MSK 0x0000002d
+#define CM_IDLEST_WKUP 0x0c20
+#define CM_AUTOIDLE_WKUP 0x0c30
+#define CM_CLKSEL_WKUP 0x0c40
+#define RM_RSTCTRL_WKUP 0x0c50
+#define RM_RSTTIME_WKUP 0x0c54
+#define RM_RSTST_WKUP 0x0c58
+#define PM_WKEN_WKUP 0x0cA0
+#define PM_WKST_WKUP 0x0cB0
+#define CM_CLKEN_PLL 0x0d00
+#define CM_CLKEN2_PLL 0x0d04
+#define CM_IDLEST_CKGEN 0x0d20
+#define CM_AUTOIDLE_PLL 0x0d30
+#define CM_AUTOIDLE2_PLL 0x0d34
+#define CM_CLKSEL1_PLL 0x0d40
+#define CM_CLKSEL2_PLL 0x0d44
+#define CM_CLKSEL3_PLL 0x0d48
+#define CM_CLKSEL4_PLL 0x0d4C
+#define CM_CLKSEL5_PLL 0x0d50
+#define CM_FCLKEN_PER 0x1000
+#define CM_FCLKEN_PER_MSK 0x0003ffff
+#define CM_ICLKEN_PER 0x1010
+#define CM_ICLKEN_PER_MSK 0x0003ffff
+#define CM_IDLEST_PER 0x1020
+#define CM_AUTOIDLE_PER 0x1030
+#define CM_CLKSEL_PER 0x1040
+#define CM_SLEEPDEP_PER 0x1044
+#define CM_CLKSTCTRL_PER 0x1048
+#define CM_CLKSTST_PER 0x104C
+#define CM_CLKSEL1_EMU 0x1140
+#define CM_CLKSTCTRL_EMU 0x1148
+#define CM_CLKSTST_EMU 0x114C
+#define CM_CLKSEL2_EMU 0x1150
+#define CM_CLKSEL3_EMU 0x1154
+#define CM_POLCTRL 0x129C
+#define CM_IDLEST_NEON 0x1320
+#define CM_CLKSTCTRL_NEON 0x1348
+#define CM_FCLKEN_USBHOST 0x1400
+#define CM_FCLKEN_USBHOST_MSK 0x00000003
+#define CM_ICLKEN_USBHOST 0x1410
+#define CM_ICLKEN_USBHOST_MSK 0x00000001
+#define CM_IDLEST_USBHOST 0x1420
+#define CM_AUTOIDLE_USBHOST 0x1430
+#define CM_SLEEPDEP_USBHOST 0x1444
+#define CM_CLKSTCTRL_USBHOST 0x1448
+#define CM_CLKSTST_USBHOST 0x144C
+
+
+#define PRCM_REG_CORE_CLK1 0
+#define PRCM_REG_CORE_CLK1_FADDR CM_FCLKEN1_CORE
+#define PRCM_REG_CORE_CLK1_IADDR CM_ICLKEN1_CORE
+#define PRCM_REG_CORE_CLK1_FMASK CM_FCLKEN1_CORE_MSK
+#define PRCM_REG_CORE_CLK1_IMASK CM_ICLKEN1_CORE_MSK
+#define PRCM_REG_CORE_CLK1_BASE (PRCM_REG_CORE_CLK1*32)
+#define PRCM_CLK_EN_MMC3 (PRCM_REG_CORE_CLK1_BASE + 30)
+#define PRCM_CLK_EN_ICR (PRCM_REG_CORE_CLK1_BASE + 29)
+#define PRCM_CLK_EN_AES2 (PRCM_REG_CORE_CLK1_BASE + 28)
+#define PRCM_CLK_EN_SHA12 (PRCM_REG_CORE_CLK1_BASE + 27)
+#define PRCM_CLK_EN_DES2 (PRCM_REG_CORE_CLK1_BASE + 26)
+#define PRCM_CLK_EN_MMC2 (PRCM_REG_CORE_CLK1_BASE + 25)
+#define PRCM_CLK_EN_MMC1 (PRCM_REG_CORE_CLK1_BASE + 24)
+#define PRCM_CLK_EN_MSPRO (PRCM_REG_CORE_CLK1_BASE + 23)
+#define PRCM_CLK_EN_HDQ (PRCM_REG_CORE_CLK1_BASE + 22)
+#define PRCM_CLK_EN_MCSPI4 (PRCM_REG_CORE_CLK1_BASE + 21)
+#define PRCM_CLK_EN_MCSPI3 (PRCM_REG_CORE_CLK1_BASE + 20)
+#define PRCM_CLK_EN_MCSPI2 (PRCM_REG_CORE_CLK1_BASE + 19)
+#define PRCM_CLK_EN_MCSPI1 (PRCM_REG_CORE_CLK1_BASE + 18)
+#define PRCM_CLK_EN_I2C3 (PRCM_REG_CORE_CLK1_BASE + 17)
+#define PRCM_CLK_EN_I2C2 (PRCM_REG_CORE_CLK1_BASE + 16)
+#define PRCM_CLK_EN_I2C1 (PRCM_REG_CORE_CLK1_BASE + 15)
+#define PRCM_CLK_EN_UART2 (PRCM_REG_CORE_CLK1_BASE + 14)
+#define PRCM_CLK_EN_UART1 (PRCM_REG_CORE_CLK1_BASE + 13)
+#define PRCM_CLK_EN_GPT11 (PRCM_REG_CORE_CLK1_BASE + 12)
+#define PRCM_CLK_EN_GPT10 (PRCM_REG_CORE_CLK1_BASE + 11)
+#define PRCM_CLK_EN_MCBSP5 (PRCM_REG_CORE_CLK1_BASE + 10)
+#define PRCM_CLK_EN_MCBSP1 (PRCM_REG_CORE_CLK1_BASE + 9)
+#define PRCM_CLK_EN_MAILBOXES (PRCM_REG_CORE_CLK1_BASE + 7)
+#define PRCM_CLK_EN_OMAPCTRL (PRCM_REG_CORE_CLK1_BASE + 6)
+#define PRCM_CLK_EN_HSOTGUSB (PRCM_REG_CORE_CLK1_BASE + 4)
+#define PRCM_CLK_EN_SDRC (PRCM_REG_CORE_CLK1_BASE + 1)
+
+#define PRCM_REG_CORE_CLK2 1
+#define PRCM_REG_CORE_CLK2_FADDR CM_FCLKEN2_CORE
+#define PRCM_REG_CORE_CLK2_IADDR CM_ICLKEN2_CORE
+#define PRCM_REG_CORE_CLK2_FMASK CM_FCLKEN2_CORE_MSK
+#define PRCM_REG_CORE_CLK2_IMASK CM_ICLKEN2_CORE_MSK
+#define PRCM_REG_CORE_CLK2_BASE (PRCM_REG_CORE_CLK2*32)
+
+#define PRCM_REG_CORE_CLK3 2
+#define PRCM_REG_CORE_CLK3_FADDR CM_FCLKEN3_CORE
+#define PRCM_REG_CORE_CLK3_IADDR CM_ICLKEN3_CORE
+#define PRCM_REG_CORE_CLK3_FMASK CM_FCLKEN3_CORE_MSK
+#define PRCM_REG_CORE_CLK3_IMASK CM_ICLKEN3_CORE_MSK
+#define PRCM_REG_CORE_CLK3_BASE (PRCM_REG_CORE_CLK3*32)
+#define PRCM_CORE_EN_USBTLL (PRCM_REG_CORE_CLK3_BASE + 2)
+#define PRCM_CORE_EN_TS (PRCM_REG_CORE_CLK3_BASE + 1)
+#define PRCM_CORE_EN_CPEFUSE (PRCM_REG_CORE_CLK3_BASE + 0)
+
+#define PRCM_REG_WKUP 3
+#define PRCM_REG_WKUP_FADDR CM_FCLKEN_WKUP
+#define PRCM_REG_WKUP_IADDR CM_ICLKEN_WKUP
+#define PRCM_REG_WKUP_FMASK CM_FCLKEN_WKUP_MSK
+#define PRCM_REG_WKUP_IMASK CM_ICLKEN_WKUP_MSK
+#define PRCM_REG_WKUP_BASE (PRCM_REG_WKUP*32)
+#define PRCM_CLK_EN_MPU_WDT (PRCM_REG_WKUP_BASE + 5)
+#define PRCM_CLK_EN_GPIO1 (PRCM_REG_WKUP_BASE + 3)
+#define PRCM_CLK_EN_32KSYNC (PRCM_REG_WKUP_BASE + 2)
+#define PRCM_CLK_EN_GPT1 (PRCM_REG_WKUP_BASE + 0)
+
+#define PRCM_REG_PER 4
+#define PRCM_REG_PER_FADDR CM_FCLKEN_PER
+#define PRCM_REG_PER_IADDR CM_ICLKEN_PER
+#define PRCM_REG_PER_FMASK CM_FCLKEN_PER_MSK
+#define PRCM_REG_PER_IMASK CM_ICLKEN_PER_MSK
+#define PRCM_REG_PER_BASE (PRCM_REG_PER*32)
+#define PRCM_CLK_EN_GPIO6 (PRCM_REG_PER_BASE + 17)
+#define PRCM_CLK_EN_GPIO5 (PRCM_REG_PER_BASE + 16)
+#define PRCM_CLK_EN_GPIO4 (PRCM_REG_PER_BASE + 15)
+#define PRCM_CLK_EN_GPIO3 (PRCM_REG_PER_BASE + 14)
+#define PRCM_CLK_EN_GPIO2 (PRCM_REG_PER_BASE + 13)
+#define PRCM_CLK_EN_WDT3 (PRCM_REG_PER_BASE + 12)
+#define PRCM_CLK_EN_UART3 (PRCM_REG_PER_BASE + 11)
+#define PRCM_CLK_EN_GPT9 (PRCM_REG_PER_BASE + 10)
+#define PRCM_CLK_EN_GPT8 (PRCM_REG_PER_BASE + 9)
+#define PRCM_CLK_EN_GPT7 (PRCM_REG_PER_BASE + 8)
+#define PRCM_CLK_EN_GPT6 (PRCM_REG_PER_BASE + 7)
+#define PRCM_CLK_EN_GPT5 (PRCM_REG_PER_BASE + 6)
+#define PRCM_CLK_EN_GPT4 (PRCM_REG_PER_BASE + 5)
+#define PRCM_CLK_EN_GPT3 (PRCM_REG_PER_BASE + 4)
+#define PRCM_CLK_EN_GPT2 (PRCM_REG_PER_BASE + 3)
+#define PRCM_CLK_EN_MCBSP4 (PRCM_REG_PER_BASE + 2)
+#define PRCM_CLK_EN_MCBSP3 (PRCM_REG_PER_BASE + 1)
+#define PRCM_CLK_EN_MCBSP2 (PRCM_REG_PER_BASE + 0)
+
+#define PRCM_REG_USBHOST 5
+#define PRCM_REG_USBHOST_FADDR CM_FCLKEN_USBHOST
+#define PRCM_REG_USBHOST_IADDR CM_ICLKEN_USBHOST
+#define PRCM_REG_USBHOST_FMASK CM_FCLKEN_USBHOST_MSK
+#define PRCM_REG_USBHOST_IMASK CM_ICLKEN_USBHOST_MSK
+#define PRCM_REG_USBHOST_BASE (PRCM_REG_USBHOST*32)
+#define PRCM_CLK_EN_USBHOST2 (PRCM_REG_USBHOST_BASE + 1)
+#define PRCM_CLK_EN_USBHOST1 (PRCM_REG_USBHOST_BASE + 0)
+#define PRCM_CLK_EN_USB (PRCM_REG_USBHOST_BASE + 0)
--- /dev/null
+/* $OpenBSD: omap4.c,v 1.3 2013/11/06 19:03:07 syl Exp $ */
+
+/*
+ * Copyright (c) 2011 Uwe Stuehler <uwe@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <armv7/armv7/armv7var.h>
+
+#define OMAPID_ADDR 0x4a002000
+#define OMAPID_SIZE 0x1000
+
+#define WD_ADDR 0x4a314000
+#define WD_SIZE 0x80
+
+#define GPIOx_SIZE 0x1000
+#define GPIO1_ADDR 0x4a310000
+#define GPIO2_ADDR 0x48055000
+#define GPIO3_ADDR 0x48057000
+#define GPIO4_ADDR 0x48059000
+#define GPIO5_ADDR 0x4805b000
+#define GPIO6_ADDR 0x4805d000
+
+#define GPIO1_IRQ 29
+#define GPIO2_IRQ 30
+#define GPIO3_IRQ 31
+#define GPIO4_IRQ 32
+#define GPIO5_IRQ 33
+#define GPIO6_IRQ 34
+
+#define UARTx_SIZE 0x400
+#define UART1_ADDR 0x4806A000
+#define UART2_ADDR 0x4806C000
+#define UART3_ADDR 0x48020000
+#define UART4_ADDR 0x4806E000
+
+#define UART1_IRQ 72
+#define UART2_IRQ 73
+#define UART3_IRQ 74
+#define UART4_IRQ 70
+
+#define HSMMCx_SIZE 0x200
+#define HSMMC1_ADDR 0x4809c100
+#define HSMMC1_IRQ 83
+
+#define PRM_ADDR 0x4a306000
+#define PRM_SIZE 0x2000
+#define CM1_ADDR 0x4a004000
+#define CM1_SIZE 0x1000
+#define CM2_ADDR 0x4a008000
+#define CM2_SIZE 0x2000
+#define SCRM_ADDR 0x4a30a000
+#define SCRM_SIZE 0x1000
+#define PCNF1_ADDR 0x4a100000
+#define PCNF1_SIZE 0x1000
+#define PCNF2_ADDR 0x4a31e000
+#define PCNF2_SIZE 0x1000
+
+#define HSUSBHOST_ADDR 0x4a064000
+#define HSUSBHOST_SIZE 0x800
+#define USBEHCI_ADDR 0x4a064c00
+#define USBEHCI_SIZE 0x400
+#define USBOHCI_ADDR 0x4a064800
+#define USBOHCI_SIZE 0x400
+#define USBEHCI_IRQ 77
+
+struct armv7_dev omap4_devs[] = {
+
+ /*
+ * Power, Reset and Clock Manager
+ */
+
+ { .name = "prcm",
+ .unit = 0,
+ .mem = {
+ { PRM_ADDR, PRM_SIZE },
+ { CM1_ADDR, CM1_SIZE },
+ { CM2_ADDR, CM2_SIZE },
+ },
+ },
+
+ /*
+ * OMAP identification registers/fuses
+ */
+
+ { .name = "omapid",
+ .unit = 0,
+ .mem = { { OMAPID_ADDR, OMAPID_SIZE } },
+ },
+
+ /*
+ * GPIO
+ */
+
+ { .name = "omgpio",
+ .unit = 0,
+ .mem = { { GPIO1_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO1_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 1,
+ .mem = { { GPIO2_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO2_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 2,
+ .mem = { { GPIO3_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO3_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 3,
+ .mem = { { GPIO4_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO4_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 4,
+ .mem = { { GPIO5_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO5_IRQ }
+ },
+
+ { .name = "omgpio",
+ .unit = 5,
+ .mem = { { GPIO6_ADDR, GPIOx_SIZE } },
+ .irq = { GPIO6_IRQ }
+ },
+
+ /*
+ * Watchdog Timer
+ */
+
+ { .name = "omdog",
+ .unit = 0,
+ .mem = { { WD_ADDR, WD_SIZE } }
+ },
+
+ /*
+ * UART
+ */
+
+ { .name = "com",
+ .unit = 2,
+ .mem = { { UART3_ADDR, UARTx_SIZE } },
+ .irq = { UART3_IRQ }
+ },
+
+ /*
+ * MMC
+ */
+
+ { .name = "ommmc",
+ .unit = 0,
+ .mem = { { HSMMC1_ADDR, HSMMCx_SIZE } },
+ .irq = { HSMMC1_IRQ }
+ },
+
+ /*
+ * USB
+ */
+
+ { .name = "ehci",
+ .unit = 0,
+ .mem = {
+ { USBEHCI_ADDR, USBEHCI_SIZE },
+ { HSUSBHOST_ADDR, HSUSBHOST_SIZE },
+ },
+ .irq = { USBEHCI_IRQ }
+ },
+
+ /* Terminator */
+ { .name = NULL,
+ .unit = 0,
+ }
+};
+
+void
+omap4_init(void)
+{
+ armv7_set_devs(omap4_devs);
+}
--- /dev/null
+/* $OpenBSD: omap4_prcmreg.h,v 1.1 2013/09/04 14:38:30 patrick Exp $ */
+/*
+ * Copyright (c) 2007, 2009, 2012 Dale Rahn <drahn@dalerahn.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define O4_L3INIT_CM2_OFFSET 0x00001300
+#define O4_CLKCTRL_MODULEMODE_MASK 0x00000003
+#define O4_CLKCTRL_MODULEMODE_DISABLE 0x00000000
+#define O4_CLKCTRL_MODULEMODE_AUTO 0x00000001
+#define O4_CLKCTRL_MODULEMODE_ENABLE 0x00000001
+
+#define O4_MAX_MODULE_ENABLE_WAIT 1000
+
+#define O4_CLKCTRL_IDLEST_MASK 0x00030000UL
+#define O4_CLKCTRL_IDLEST_ENABLED 0x00000000UL
--- /dev/null
+/* $OpenBSD: omap_com.c,v 1.2 2013/11/06 19:03:07 syl Exp $ */
+/*
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/tty.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+
+/* pick up armv7_a4x_bs_tag */
+#include <arch/arm/armv7/armv7var.h>
+
+#include <armv7/armv7/armv7var.h>
+
+#define com_isr 8
+#define ISR_RECV (ISR_RXPL | ISR_XMODE | ISR_RCVEIR)
+
+void omapuart_attach(struct device *, struct device *, void *);
+int omapuart_activate(struct device *, int);
+
+struct cfattach com_omap_ca = {
+ sizeof (struct com_softc), NULL, omapuart_attach, NULL,
+ omapuart_activate
+};
+
+void
+omapuart_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct com_softc *sc = (struct com_softc *)self;
+ struct armv7_attach_args *aa = aux;
+
+ sc->sc_iot = &armv7_a4x_bs_tag; /* XXX: This sucks */
+ sc->sc_iobase = aa->aa_dev->mem[0].addr;
+ sc->sc_frequency = 48000000;
+ sc->sc_uarttype = COM_UART_TI16750;
+
+ if (bus_space_map(sc->sc_iot, sc->sc_iobase,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_ioh)) {
+ printf("%s: bus_space_map failed\n", __func__);
+ return;
+ }
+
+ com_attach_subr(sc);
+
+ (void)arm_intr_establish(aa->aa_dev->irq[0], IPL_TTY, comintr,
+ sc, sc->sc_dev.dv_xname);
+}
+
+int
+omapuart_activate(struct device *self, int act)
+{
+ struct com_softc *sc = (struct com_softc *)self;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
+ struct tty *tp = sc->sc_tty;
+
+ switch (act) {
+ case DVACT_SUSPEND:
+ break;
+ case DVACT_RESUME:
+ if (sc->enabled) {
+ sc->sc_initialize = 1;
+ comparam(tp, &tp->t_termios);
+ bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
+
+ if (ISSET(sc->sc_hwflags, COM_HW_SIR)) {
+ bus_space_write_1(iot, ioh, com_isr,
+ ISR_RECV);
+ }
+ }
+ break;
+ }
+ return 0;
+}
--- /dev/null
+/* $OpenBSD: omap_machdep.c,v 1.6 2015/05/19 03:30:54 jsg Exp $ */
+/*
+ * Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/termios.h>
+
+#include <machine/bus.h>
+#include <machine/bootconfig.h>
+
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+
+#include <arm/cortex/smc.h>
+#include <arm/armv7/armv7var.h>
+#include <armv7/armv7/armv7var.h>
+#include <armv7/armv7/armv7_machdep.h>
+
+extern void omap4_smc_call(uint32_t, uint32_t);
+extern void omdog_reset(void);
+extern char *omap_board_name(void);
+extern struct board_dev *omap_board_devs(void);
+extern void omap_board_init(void);
+extern int comcnspeed;
+extern int comcnmode;
+
+void
+omap_platform_smc_write(bus_space_tag_t iot, bus_space_handle_t ioh,
+ bus_size_t off, uint32_t op, uint32_t val)
+{
+ switch (op) {
+ case 0x100: /* PL310 DEBUG */
+ case 0x102: /* PL310 CTL */
+ break;
+ default:
+ panic("platform_smc_write: invalid operation %d", op);
+ }
+
+ omap4_smc_call(op, val);
+}
+
+void
+omap_platform_init_cons(void)
+{
+ paddr_t paddr;
+
+ switch (board_id) {
+ case BOARD_ID_OMAP3_BEAGLE:
+ case BOARD_ID_OMAP3_OVERO:
+ paddr = 0x49020000;
+ break;
+ case BOARD_ID_AM335X_BEAGLEBONE:
+ paddr = 0x44e09000;
+ break;
+ case BOARD_ID_OMAP4_PANDA:
+ paddr = 0x48020000;
+ break;
+ }
+
+ comcnattach(&armv7_a4x_bs_tag, paddr, comcnspeed, 48000000, comcnmode);
+ comdefaultrate = comcnspeed;
+}
+
+void
+omap_platform_watchdog_reset(void)
+{
+ omdog_reset();
+}
+
+void
+omap_platform_powerdown(void)
+{
+
+}
+
+const char *
+omap_platform_board_name(void)
+{
+ return (omap_board_name());
+}
+
+void
+omap_platform_disable_l2_if_needed(void)
+{
+ switch (board_id) {
+ case BOARD_ID_OMAP4_PANDA:
+ /* disable external L2 cache */
+ omap4_smc_call(0x102, 0);
+ break;
+ }
+}
+
+void
+omap_platform_board_init(void)
+{
+ omap_board_init();
+}
+
+struct armv7_platform omap_platform = {
+ .boot_name = "OpenBSD/omap",
+ .board_name = omap_platform_board_name,
+ .board_init = omap_platform_board_init,
+ .smc_write = omap_platform_smc_write,
+ .init_cons = omap_platform_init_cons,
+ .watchdog_reset = omap_platform_watchdog_reset,
+ .powerdown = omap_platform_powerdown,
+ .disable_l2_if_needed = omap_platform_disable_l2_if_needed,
+};
+
+struct armv7_platform *
+omap_platform_match(void)
+{
+ struct board_dev *devs;
+
+ devs = omap_board_devs();
+ if (devs == NULL)
+ return (NULL);
+
+ omap_platform.devs = devs;
+ return (&omap_platform);
+}
--- /dev/null
+/* $OpenBSD: omapid.c,v 1.2 2013/11/06 19:03:07 syl Exp $ */
+/*
+ * Copyright (c) 2013 Dale Rahn <drahn@dalerahn.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/evcount.h>
+#include <sys/socket.h>
+#include <sys/timeout.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <armv7/armv7/armv7var.h>
+
+/* registers */
+#define O4_ID_SIZE 0x1000
+#define O4_FUSE_ID0 0x200
+#define O4_ID_CODE 0x204
+#define O4_FUSE_ID1 0x208
+#define O4_FUSE_ID2 0x20C
+#define O4_FUSE_ID3 0x210
+#define O4_FUSE_PRODID0 0x214
+#define O4_FUSE_PRODID1 0x218
+
+
+struct omapid_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+struct omapid_softc *omapid_sc;
+
+
+void omapid_attach(struct device *parent, struct device *self, void *args);
+void omapid_wpending(int flags);
+
+struct cfattach omapid_ca = {
+ sizeof (struct omapid_softc), NULL, omapid_attach
+};
+
+struct cfdriver omapid_cd = {
+ NULL, "omapid", DV_DULL
+};
+
+void amptimer_set_clockrate(int32_t new_frequency); /* XXX */
+
+void
+omapid_attach(struct device *parent, struct device *self, void *args)
+{
+ struct armv7_attach_args *aa = args;
+ struct omapid_softc *sc = (struct omapid_softc *) self;
+ uint32_t rev;
+ uint32_t newclockrate = 0;
+ char *board;
+
+ sc->sc_iot = aa->aa_iot;
+ if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
+ panic("omapid: bus_space_map failed!");
+
+ omapid_sc = sc;
+
+ board = "unknown";
+ switch (board_id) {
+ case BOARD_ID_OMAP4_PANDA:
+ rev = bus_space_read_4(sc->sc_iot, sc->sc_ioh, O4_ID_CODE);
+ switch ((rev >> 12) & 0xffff) {
+ case 0xB852:
+ case 0xB95C:
+ board = "omap4430";
+ newclockrate = 400 * 1000 * 1000;
+ break;
+ case 0xB94E:
+ board = "omap4460";
+ newclockrate = 350 * 1000 * 1000;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ printf(": %s\n", board);
+ if (newclockrate != 0)
+ amptimer_set_clockrate(newclockrate);
+}
--- /dev/null
+/* $OpenBSD: omdisplay.c,v 1.5 2014/07/12 18:44:41 tedu Exp $ */
+/*
+ * Copyright (c) 2007 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/evcount.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <machine/bus.h>
+#include <armv7/omap/omgpiovar.h>
+
+#include <dev/cons.h>
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wscons_callbacks.h>
+
+#include <dev/rasops/rasops.h>
+
+#include "splash16.h"
+
+#define OMDISPLAY_SIZE 0x1000
+/* registers */
+/* DSS */
+#define DSS_REVISIONNUMBER 0x00
+#define DSS_CONTROL 0x40
+#define DSS_PSA_LCD_REG_1 0x50
+#define DSS_PSA_LCD_REG_2 0x54
+#define DSS_PSA_VIDEO_REG 0x58
+#define DSS_STATUS 0x5C
+
+/* DCR */
+#define DISPC_REVISION 0x0000
+#define DISPC_SYSCONFIG 0x0010
+#define DISPC_SYSCONFIG_AUTOIDLE 0x00000001
+#define DISPC_SYSCONFIG_SOFTRESET 0x00000002
+#define DISPC_SYSCONFIG_SIDLEMODE_FORCE 0x00000000
+#define DISPC_SYSCONFIG_SIDLEMODE_NONE 0x00000008
+#define DISPC_SYSCONFIG_SIDLEMODE_SMART 0x00000010
+#define DISPC_SYSCONFIG_MIDLEMODE_FORCE 0x00000000
+#define DISPC_SYSCONFIG_MIDLEMODE_NONE 0x00001000
+#define DISPC_SYSCONFIG_MIDLEMODE_SMART 0x00002000
+#define DISPC_SYSSTATUS 0x0014
+#define DISPC_SYSTATUS_RESETDONE 0x00000001
+#define DISPC_IRQSTATUS 0x0018
+#define DISPC_IRQSTATUS_FRAMEDONE 0x00000001
+#define DISPC_IRQSTATUS_VSYNC 0x00000002
+#define DISPC_IRQSTATUS_EVSYNCEVEN 0x00000004
+#define DISPC_IRQSTATUS_EVSYNCODD 0x00000008
+#define DISPC_IRQSTATUS_ACBIASCOUNT 0x00000010
+#define DISPC_IRQSTATUS_PROGLINENUM 0x00000020
+#define DISPC_IRQSTATUS_GFXFIFOUNDER 0x00000040
+#define DISPC_IRQSTATUS_GFXENDWINDOW 0x00000080
+#define DISPC_IRQSTATUS_PALGAMMA 0x00000100
+#define DISPC_IRQSTATUS_OCPERROR 0x00000200
+#define DISPC_IRQSTATUS_VID1FIFOUNDER 0x00000400
+#define DISPC_IRQSTATUS_VID1ENDWIND 0x00000800
+#define DISPC_IRQSTATUS_VID2FIFOUNDER 0x00001000
+#define DISPC_IRQSTATUS_VID2ENDWIND 0x00002000
+#define DISPC_IRQSTATUS_SYNCLOST 0x00004000
+#define DISPC_IRQENABLE 0x001C
+#define DISPC_IRQENABLE_FRAMEDONE 0x00000001
+#define DISPC_IRQENABLE_VSYNC 0x00000002
+#define DISPC_IRQENABLE_EVSYNCEVEN 0x00000004
+#define DISPC_IRQENABLE_EVSYNCODD 0x00000008
+#define DISPC_IRQENABLE_ACBIASCOUNT 0x00000010
+#define DISPC_IRQENABLE_PROGLINENUM 0x00000020
+#define DISPC_IRQENABLE_GFXFIFOUNDER 0x00000040
+#define DISPC_IRQENABLE_GFXENDWINDOW 0x00000080
+#define DISPC_IRQENABLE_PALGAMMA 0x00000100
+#define DISPC_IRQENABLE_OCPERROR 0x00000200
+#define DISPC_IRQENABLE_VID1FIFOUNDER 0x00000400
+#define DISPC_IRQENABLE_VID1ENDWIND 0x00000800
+#define DISPC_IRQENABLE_VID2FIFOUNDER 0x00001000
+#define DISPC_IRQENABLE_VID2ENDWIND 0x00002000
+#define DISPC_IRQENABLE_SYNCLOST 0x00004000
+#define DISPC_CONTROL 0x0040
+#define DISPC_CONTROL_LCDENABLE 0x00000001
+#define DISPC_CONTROL_DIGITALENABLE 0x00000002
+#define DISPC_CONTROL_MONOCOLOR 0x00000004
+#define DISPC_CONTROL_STNTFT 0x00000008
+#define DISPC_CONTROL_M8B 0x00000010
+#define DISPC_CONTROL_GOLCD 0x00000020
+#define DISPC_CONTROL_GODIGITAL 0x00000040
+#define DISPC_CONTROL_TFTDITHEREN 0x00000080
+#define DISPC_CONTROL_TFTDATALINES_12 0x00000000
+#define DISPC_CONTROL_TFTDATALINES_16 0x00000100
+#define DISPC_CONTROL_TFTDATALINES_18 0x00000200
+#define DISPC_CONTROL_TFTDATALINES_24 0x00000300
+#define DISPC_CONTROL_SECURE 0x00000400
+#define DISPC_CONTROL_RFBIMODE 0x00000800
+#define DISPC_CONTROL_OVERLAYOPT 0x00001000
+#define DISPC_CONTROL_GPIN0 0x00002000
+#define DISPC_CONTROL_GPIN1 0x00004000
+#define DISPC_CONTROL_GPOUT0 0x00008000
+#define DISPC_CONTROL_GPOUT1 0x00010000
+#define DISPC_CONTROL_HT 0x00070000
+#define DISPC_CONTROL_HT_s(x) ((x) << 17)
+#define DISPC_CONTROL_TDMENABLE 0x00100000
+#define DISPC_CONTROL_TDMPARALLEL_8 0x00000000
+#define DISPC_CONTROL_TDMPARALLEL_9 0x00200000
+#define DISPC_CONTROL_TDMPARALLEL_12 0x00400000
+#define DISPC_CONTROL_TDMPARALLEL_16 0x00600000
+#define DISPC_CONTROL_TDMCYCLE_1 0x00000000
+#define DISPC_CONTROL_TDMCYCLE_2 0x00800000
+#define DISPC_CONTROL_TDMCYCLE_3 0x00000000
+#define DISPC_CONTROL_TDMCYCLE_3_2 0x01800000
+#define DISPC_CONTROL_TDMUNUSED_0 0x00000000
+#define DISPC_CONTROL_TDMUNUSED_1 0x02000000
+#define DISPC_CONTROL_TDMUNUSED_M 0x04000000
+#define DISPC_CONFIG 0x0044
+#define DISPC_CONFIG_PIXELGATED 0x00000001
+#define DISPC_CONFIG_LOADMODE_PGE 0x00000000
+#define DISPC_CONFIG_LOADMODE_PG 0x00000002
+#define DISPC_CONFIG_LOADMODE_DATA 0x00000004
+#define DISPC_CONFIG_LOADMODE_DATA_PG 0x00000006
+#define DISPC_CONFIG_PALETTEGAMMA 0x00000008
+#define DISPC_CONFIG_PIXELDATAGATED 0x00000010
+#define DISPC_CONFIG_PIXELCLOCKGATED 0x00000020
+#define DISPC_CONFIG_HSYNCGATED 0x00000040
+#define DISPC_CONFIG_VSYNCGATED 0x00000080
+#define DISPC_CONFIG_ACBIAGATED 0x00000100
+#define DISPC_CONFIG_FUNCGATED 0x00000200
+#define DISPC_CONFIG_TCKLCDEN 0x00000400
+#define DISPC_CONFIG_TCKLCDSEL 0x00000800
+#define DISPC_CONFIG_TCKDIGEN 0x00001000
+#define DISPC_CONFIG_TCKDIGSEL 0x00002000
+#define DISPC_CAPABLE 0x0048
+#define DISPC_DEFAULT_COLOR0 0x004C
+#define DISPC_DEFAULT_COLOR1 0x0050
+#define DISPC_TRANS_COLOR0 0x0054
+#define DISPC_TRANS_COLOR1 0x0058
+#define DISPC_LINE_STATUS 0x005C
+#define DISPC_LINE_NUMBER 0x0060
+#define DISPC_TIMING_H 0x0064
+#define DISPC_TIMING_H_HSW_s(x) ((x) << 0)
+#define DISPC_TIMING_H_HFP_s(x) ((x) << 8)
+#define DISPC_TIMING_H_HBP_s(x) ((x) << 20)
+#define DISPC_TIMING_V 0x0068
+#define DISPC_TIMING_V_VSW_s(x) ((x) << 0)
+#define DISPC_TIMING_V_VFP_s(x) ((x) << 8)
+#define DISPC_TIMING_V_VBP_s(x) ((x) << 20)
+#define DISPC_POL_FREQ 0x006C
+#define DISPC_POL_FREQ_ACB_s(x) ((x) << 0)
+#define DISPC_POL_FREQ_ACBI_s(x) ((x) << 8)
+#define DISPC_POL_FREQ_IVS 0x00001000
+#define DISPC_POL_FREQ_IHS 0x00002000
+#define DISPC_POL_FREQ_IPC 0x00004000
+#define DISPC_POL_FREQ_IEO 0x00008000
+#define DISPC_POL_FREQ_RF 0x00010000
+#define DISPC_POL_FREQ_ONOFF 0x00020000
+#define DISPC_DIVISOR 0x0070
+#define DISPC_DIVISOR_PCD_s(x) ((x) << 0)
+#define DISPC_DIVISOR_LCD_s(x) ((x) << 16)
+#define DISPC_SIZE_DIG 0x0078
+#define DISPC_SIZE_DIG_PPL_s(x) ((x) << 0)
+#define DISPC_SIZE_DIG_LPP_s(x) ((x) << 16)
+#define DISPC_SIZE_LCD 0x007C
+#define DISPC_SIZE_LCD_PPL_s(x) ((x) << 0)
+#define DISPC_SIZE_LCD_LPP_s(x) ((x) << 16)
+#define DISPC_GFX_BA0 0x0080
+#define DISPC_GFX_BA1 0x0084
+#define DISPC_GFX_POSITION 0x0088
+#define DISPC_GFX_SIZE 0x008C
+#define DISPC_GFX_SIZE_X_s(x) ((x) << 0)
+#define DISPC_GFX_SIZE_Y_s(x) ((x) << 16)
+#define DISPC_GFX_ATTRIBUTES 0x00A0
+#define DISPC_GFX_ATTRIBUTES_GFXENABLE 0x001
+#define DISPC_GFX_ATTRIBUTES_GFXFMT_1 0x000
+#define DISPC_GFX_ATTRIBUTES_GFXFMT_2 0x002
+#define DISPC_GFX_ATTRIBUTES_GFXFMT_4 0x004
+#define DISPC_GFX_ATTRIBUTES_GFXFMT_8 0x006
+#define DISPC_GFX_ATTRIBUTES_GFXFMT_12 0x008
+#define DISPC_GFX_ATTRIBUTES_GFXFMT_16 0x00c
+#define DISPC_GFX_ATTRIBUTES_GFXFMT_24 0x010
+#define DISPC_GFX_ATTRIBUTES_GFXREPLICATE 0x020
+#define DISPC_GFX_ATTRIBUTES_BURST_4 0x000
+#define DISPC_GFX_ATTRIBUTES_BURST_8 0x040
+#define DISPC_GFX_ATTRIBUTES_BURST_16 0x080
+#define DISPC_GFX_ATTRIBUTES_GFXCHANNELOUT 0x100
+#define DISPC_GFX_ATTRIBUTES_NIBBLEMODE 0x200
+#define DISPC_GFX_ATTRIBUTES_ENDIAN 0x400
+#define DISPC_GFX_FIFO_THRESHOLD 0x00A4
+#define DISPC_GFX_FIFO_THRESHOLD_HIGH_SHIFT 16
+#define DISPC_GFX_FIFO_THRESHOLD_LOW_SHIFT 0
+#define DISPC_GFX_FIFO_SIZE_STATUS 0x00A8
+#define DISPC_GFX_ROW_INC 0x00AC
+#define DISPC_GFX_PIXEL_INC 0x00B0
+#define DISPC_GFX_WINDOW_SKIP 0x00B4
+#define DISPC_GFX_TABLE_BA 0x00B8
+#define DISPC_VID1_BA0 0x00BC
+#define DISPC_VID1_BA1 0x00C0
+#define DISPC_VID1_POSITION 0x00C4
+#define DISPC_VID1_SIZE 0x00C8
+#define DISPC_VID1_ATTRIBUTES 0x00CC
+#define DISPC_VID1_FIFO_THRESHOLD 0x00D0
+#define DISPC_VID1_FIFO_SIZE_STATUS 0x00D4
+#define DISPC_VID1_ROW_INC 0x00D8
+#define DISPC_VID1_PIXEL_INC 0x00DC
+#define DISPC_VID1_FIR 0x00E0
+#define DISPC_VID1_PICTURE_SIZE 0x00E4
+#define DISPC_VID1_ACCU0 0x00E8
+#define DISPC_VID1_ACCU1 0x00EC
+#define DISPC_VID1_FIR_COEF_H0 0x00F0
+#define DISPC_VID1_FIR_COEF_H1 0x00F8
+#define DISPC_VID1_FIR_COEF_H2 0x0100
+#define DISPC_VID1_FIR_COEF_H3 0x0108
+#define DISPC_VID1_FIR_COEF_H4 0x0110
+#define DISPC_VID1_FIR_COEF_H5 0x0118
+#define DISPC_VID1_FIR_COEF_H6 0x0120
+#define DISPC_VID1_FIR_COEF_H7 0x0128
+#define DISPC_VID1_FIR_COEF_HV0 0x00F4
+#define DISPC_VID1_FIR_COEF_HV1 0x00FC
+#define DISPC_VID1_FIR_COEF_HV2 0x0104
+#define DISPC_VID1_FIR_COEF_HV3 0x010C
+#define DISPC_VID1_FIR_COEF_HV4 0x0114
+#define DISPC_VID1_FIR_COEF_HV5 0x011C
+#define DISPC_VID1_FIR_COEF_HV6 0x0124
+#define DISPC_VID1_FIR_COEF_HV7 0x012C
+#define DISPC_VID1_CONV_COEF0 0x0130
+#define DISPC_VID1_CONV_COEF1 0x0134
+#define DISPC_VID1_CONV_COEF2 0x0138
+#define DISPC_VID1_CONV_COEF3 0x013C
+#define DISPC_VID1_CONV_COEF4 0x0140
+#define DISPC_VID2_BA0 0x014C
+#define DISPC_VID2_BA1 0x0150
+#define DISPC_VID2_POSITION 0x0154
+#define DISPC_VID2_SIZE 0x0158
+#define DISPC_VID2_ATTRIBUTES 0x015C
+#define DISPC_VID2_FIFO_THRESHOLD 0x0160
+#define DISPC_VID2_FIFO_SIZE_STATUS 0x0164
+#define DISPC_VID2_ROW_INC 0x0168
+#define DISPC_VID2_PIXEL_INC 0x016C
+#define DISPC_VID2_FIR 0x0170
+#define DISPC_VID2_PICTURE_SIZE 0x0174
+#define DISPC_VID2_ACCU0 0x0178
+#define DISPC_VID2_ACCU1 0x017C
+#define DISPC_VID2_FIR_COEF_H0 0x0180
+#define DISPC_VID2_FIR_COEF_H1 0x0188
+#define DISPC_VID2_FIR_COEF_H2 0x0190
+#define DISPC_VID2_FIR_COEF_H3 0x0198
+#define DISPC_VID2_FIR_COEF_H4 0x01A0
+#define DISPC_VID2_FIR_COEF_H5 0x01A8
+#define DISPC_VID2_FIR_COEF_H6 0x01B0
+#define DISPC_VID2_FIR_COEF_H7 0x01B8
+#define DISPC_VID2_FIR_COEF_HV0 0x0184
+#define DISPC_VID2_FIR_COEF_HV1 0x018C
+#define DISPC_VID2_FIR_COEF_HV2 0x0194
+#define DISPC_VID2_FIR_COEF_HV3 0x019C
+#define DISPC_VID2_FIR_COEF_HV4 0x01A4
+#define DISPC_VID2_FIR_COEF_HV5 0x01AC
+#define DISPC_VID2_FIR_COEF_HV6 0x01B4
+#define DISPC_VID2_FIR_COEF_HV7 0x01BC
+#define DISPC_VID2_CONV_COEF0 0x01C0
+#define DISPC_VID2_CONV_COEF1 0x01C4
+#define DISPC_VID2_CONV_COEF2 0x01C8
+#define DISPC_VID2_CONV_COEF3 0x01CC
+#define DISPC_VID2_CONV_COEF4 0x01D0
+#define DISPC_DATA_CYCLE1 0x01D4
+#define DISPC_DATA_CYCLE2 0x01D8
+#define DISPC_DATA_CYCLE3 0x01DC
+#define DISPC_SIZE 0x0200
+
+/* RFBI */
+#define RFBI_REVISION 0x0000
+#define RFBI_SYSCONFIG 0x0010
+#define RFBI_SYSSTATUS 0x0014
+#define RFBI_CONTROL 0x0040
+#define RFBI_PIXEL_CNT 0x0044
+#define RFBI_LINE_NUMBER 0x0048
+#define RFBI_CMD 0x004C
+#define RFBI_PARAM 0x0050
+#define RFBI_DATA 0x0054
+#define RFBI_READ 0x0058
+#define RFBI_STATUS 0x005C
+#define RFBI_CONFIG0 0x0060
+#define RFBI_CONFIG1 0x0078
+#define RFBI_ONOFF_TIME0 0x0064
+#define RFBI_ONOFF_TIME1 0x007C
+#define RFBI_CYCLE_TIME0 0x0068
+#define RFBI_CYCLE_TIME1 0x0080
+#define RFBI_DATA_CYCLE1_0 0x006C
+#define RFBI_DATA_CYCLE1_1 0x0084
+#define RFBI_DATA_CYCLE2_0 0x0070
+#define RFBI_DATA_CYCLE2_1 0x0088
+#define RFBI_DATA_CYCLE3_0 0x0074
+#define RFBI_DATA_CYCLE3_1 0x008C
+#define RFBI_VSYNC_WIDTH 0x0090
+#define RFBI_HSYNC_WIDTH 0x0094
+
+/* VENC1 */
+#define REV_ID 0x0000
+#define STATUS 0x0004
+#define F_CONTROL 0x0008
+#define VIDOUT_CTRL 0x0010
+#define SYNC_CTRL 0x0014
+#define LLEN 0x001C
+#define FLENS 0x0020
+#define HFLTR_CTRL 0x0024
+#define CC_CARR_WSS_CARR 0x0028
+#define C_PHASE 0x002C
+#define GAIN_U 0x0030
+#define GAIN_V 0x0034
+#define GAIN_Y 0x0038
+#define BLACK_LEVEL 0x003C
+#define BLANK_LEVEL 0x0040
+#define X_COLOR 0x0044
+#define M_CONTROL 0x0048
+#define BSTAMP_WSS_DATA 0x004C
+#define S_CARR 0x0050
+#define LINE21 0x0054
+#define LN_SEL 0x0058
+#define L21_WC_CTL 0x005C
+#define HTRIGGER_VTRIGGER 0x0060
+#define SAVID_EAVID 0x0064
+#define FLEN_FAL 0x0068
+#define LAL_PHASE_RESET 0x006C
+#define HS_INT_START_STOP_X 0x0070
+#define HS_EXT_START_STOP_X 0x0074
+#define VS_INT_START_X 0x0078
+#define VS_INT_STOP_X_VS_INT_START_Y 0x007C
+#define VS_INT_STOP_Y_VS_EXT_START_X 0x0080
+#define VS_EXT_STOP_X_VS_EXT_START_Y 0x0084
+#define VS_EXT_STOP_Y 0x0088
+#define AVID_START_STOP_X 0x0090
+#define AVID_START_STOP_Y 0x0094
+#define FID_INT_START_X_FID_INT_START_Y 0x00A0
+#define FID_INT_OFFSET_Y_FID_EXT_START_X 0x00A4
+#define FID_EXT_START_Y_FID_EXT_OFFSET_Y 0x00A8
+#define TVDETGP_INT_START_STOP_X 0x00B0
+#define TVDETGP_INT_START_STOP_Y 0x00B4
+#define GEN_CTRL 0x00B8
+#define DAC_TST_DAC_A 0x00C4
+#define DAC_B_DAC_C 0x00C8
+
+
+/* NO CONSOLE SUPPORT */
+
+
+/* assumes 565 panel. */
+struct omdisplay_panel_data {
+ int width;
+ int height;
+ int horiz_sync_width;
+ int horiz_front_porch;
+ int horiz_back_porch;
+ int vert_sync_width;
+ int vert_front_porch;
+ int vert_back_porch;
+ int panel_flags;
+ int sync;
+ int depth;
+#define PANEL_SYNC_H_ACTIVE_HIGH 1
+#define PANEL_SYNC_V_ACTIVE_HIGH 2
+ int linebytes;
+};
+
+#define PIXELDEPTH 16
+#define PIXELWIDTH 2
+
+struct omdisplay_panel_data default_panel = {
+ 240, /* Width */
+ 322, /* Height */
+ 9, 9, 19, /* horiz sync, fp, bp */
+ 1, 2, 2, /* vert sync, fp, bp */
+ 0, /* flags */
+ 0, /* sync */
+ PIXELDEPTH,
+ 240*PIXELWIDTH
+};
+
+struct omdisplay_screen {
+ LIST_ENTRY(omdisplay_screen) link;
+
+ /* Frame buffer */
+ bus_dmamap_t dma;
+ bus_dma_segment_t segs[1];
+ int nsegs;
+ size_t buf_size;
+ size_t map_size;
+ void *buf_va;
+ int depth;
+
+ /* rasterop */
+ struct rasops_info rinfo;
+};
+
+struct omdisplay_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_dsioh;
+ bus_space_handle_t sc_dcioh;
+ bus_space_handle_t sc_rfbioh;
+ bus_space_handle_t sc_venioh;
+ bus_dma_tag_t sc_dma_tag;
+
+ void *sc_ih;
+
+ int sc_nscreens;
+ LIST_HEAD(,omdisplay_screen) sc_screens;
+
+ struct omdisplay_panel_data *sc_geometry;
+ struct omdisplay_screen *sc_active;
+};
+
+int omdisplay_match(struct device *parent, void *v, void *aux);
+void omdisplay_attach(struct device *parent, struct device *self, void *args);
+int omdisplay_activate(struct device *, int);
+int omdisplay_ioctl(void *v, u_long cmd, caddr_t data, int flag,
+ struct proc *p);
+void omdisplay_burner(void *v, u_int on, u_int flags);
+int omdisplay_show_screen(void *v, void *cookie, int waitok,
+ void (*cb)(void *, int, int), void *cbarg);
+int omdisplay_param(struct omdisplay_softc *sc, ulong cmd,
+ struct wsdisplay_param *dp);
+int omdisplay_max_brightness(void);
+int omdisplay_get_brightness(void);
+void omdisplay_set_brightness(int newval);
+void omdisplay_set_brightness_internal(int newval);
+int omdisplay_get_backlight(void);
+void omdisplay_set_backlight(int on);
+void omdisplay_blank(int blank);
+void omdisplay_suspend(struct omdisplay_softc *sc);
+void omdisplay_resume(struct omdisplay_softc *sc);
+void omdisplay_initialize(struct omdisplay_softc *sc,
+ struct omdisplay_panel_data *geom);
+void omdisplay_setup_rasops(struct omdisplay_softc *sc,
+ struct rasops_info *rinfo);
+int omdisplay_alloc_screen(void *v, const struct wsscreen_descr *_type,
+ void **cookiep, int *curxp, int *curyp, long *attrp);
+int omdisplay_new_screen(struct omdisplay_softc *sc,
+ struct omdisplay_screen *scr, int depth);
+paddr_t omdisplay_mmap(void *v, off_t offset, int prot);
+int omdisplay_load_font(void *, void *, struct wsdisplay_font *);
+int omdisplay_list_font(void *, struct wsdisplay_font *);
+void omdisplay_free_screen(void *v, void *cookie);
+void omdisplay_start(struct omdisplay_softc *sc);
+void omdisplay_stop(struct omdisplay_softc *sc);
+int omdisplay_intr(void *v);
+void omdisplay_dumpreg(struct omdisplay_softc *sc);
+
+struct cfattach omdisplay_ca = {
+ sizeof (struct omdisplay_softc), omdisplay_match, omdisplay_attach,
+ NULL, omdisplay_activate
+};
+
+struct cfdriver omdisplay_cd = {
+ NULL, "omdisplay", DV_DULL
+};
+
+struct wsdisplay_accessops omdisplay_accessops = {
+ .ioctl = omdisplay_ioctl,
+ .mmap = omdisplay_mmap,
+ .alloc_screen = omdisplay_alloc_screen,
+ .free_screen = omdisplay_free_screen,
+ .show_screen = omdisplay_show_screen,
+ .load_font = omdisplay_load_font,
+ .list_font = omdisplay_list_font,
+ .burn_screen = omdisplay_burner
+
+};
+
+struct omdisplay_wsscreen_descr {
+ struct wsscreen_descr c; /* standard descriptor */
+ int depth; /* bits per pixel */
+ int flags; /* rasops flags */
+};
+
+struct omdisplay_wsscreen_descr omdisplay_screen = {
+ {
+ "std"
+ },
+ 16, /* bits per pixel */
+ 0 /* rotate */
+};
+
+const struct wsscreen_descr *omdisplay_scr_descr[] = {
+ &omdisplay_screen.c
+};
+
+/* XXX - what about flip phones with CLI */
+const struct wsscreen_list omdisplay_screen_list = {
+ sizeof omdisplay_scr_descr / sizeof omdisplay_scr_descr[0],
+ omdisplay_scr_descr
+};
+
+
+int
+omdisplay_match(struct device *parent, void *v, void *aux)
+{
+ /* XXX */
+ return (1);
+}
+
+void
+omdisplay_attach(struct device *parent, struct device *self, void *args)
+{
+ struct ahb_attach_args *aa = args;
+ struct omdisplay_softc *sc = (struct omdisplay_softc *) self;
+ struct wsemuldisplaydev_attach_args wsaa;
+
+
+ sc->sc_iot = aa->aa_iot;
+
+ if (bus_space_map(sc->sc_iot, aa->aa_addr, OMDISPLAY_SIZE, 0,
+ &sc->sc_dsioh))
+ panic("omdisplay_attach: bus_space_map failed!");
+
+ if (bus_space_subregion(sc->sc_iot, sc->sc_dsioh, 0x400, 1024,
+ &sc->sc_dcioh))
+ panic("omdisplay_attach: bus_space_submap failed!");
+
+ if (bus_space_subregion(sc->sc_iot, sc->sc_dsioh, 0x800, 1024,
+ &sc->sc_rfbioh))
+ panic("omdisplay_attach: bus_space_submap failed!");
+
+ if (bus_space_subregion(sc->sc_iot, sc->sc_dsioh, 0xc00, 1024,
+ &sc->sc_venioh))
+ panic("omdisplay_attach: bus_space_submap failed!");
+
+
+ sc->sc_nscreens = 0;
+ LIST_INIT(&sc->sc_screens);
+
+ sc->sc_dma_tag = aa->aa_dmat;
+
+ sc->sc_ih = arm_intr_establish(aa->aa_intr, IPL_BIO /* XXX */,
+ omdisplay_intr, sc, sc->sc_dev.dv_xname);
+
+ printf ("\n");
+
+ sc->sc_geometry = &default_panel;
+
+ {
+ /* XXX - dummy? */
+ struct rasops_info dummy;
+
+ omdisplay_initialize(sc, sc->sc_geometry);
+
+ /*
+ * Initialize a dummy rasops_info to compute fontsize and
+ * the screen size in chars.
+ */
+ bzero(&dummy, sizeof(dummy));
+ omdisplay_setup_rasops(sc, &dummy);
+ }
+
+ wsaa.console = 0;
+ wsaa.scrdata = &omdisplay_screen_list;
+ wsaa.accessops = &omdisplay_accessops;
+ wsaa.accesscookie = sc;
+ wsaa.defaultscreens = 0;
+
+ (void)config_found(self, &wsaa, wsemuldisplaydevprint);
+
+ /* backlight? */
+}
+
+
+int
+omdisplay_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ struct omdisplay_softc *sc = v;
+ struct wsdisplay_fbinfo *wsdisp_info;
+ struct omdisplay_screen *scr = sc->sc_active;
+ int res = EINVAL;
+
+ switch (cmd) {
+ case WSDISPLAYIO_GETPARAM:
+ case WSDISPLAYIO_SETPARAM:
+ res = omdisplay_param(sc, cmd, (struct wsdisplay_param *)data);
+ break;
+ case WSDISPLAYIO_GTYPE:
+ *(u_int *)data = WSDISPLAY_TYPE_PXALCD; /* XXX */
+ break;
+
+ case WSDISPLAYIO_GINFO:
+ wsdisp_info = (struct wsdisplay_fbinfo *)data;
+
+ wsdisp_info->height = sc->sc_geometry->height;
+ wsdisp_info->width = sc->sc_geometry->width;
+ wsdisp_info->depth = 16; /* XXX */
+ wsdisp_info->cmsize = 0;
+ break;
+
+ case WSDISPLAYIO_GETCMAP:
+ case WSDISPLAYIO_PUTCMAP:
+ return EINVAL; /* XXX Colormap */
+
+ case WSDISPLAYIO_SVIDEO:
+ case WSDISPLAYIO_GVIDEO:
+ break;
+
+ case WSDISPLAYIO_GCURPOS:
+ case WSDISPLAYIO_SCURPOS:
+ case WSDISPLAYIO_GCURMAX:
+ case WSDISPLAYIO_GCURSOR:
+ case WSDISPLAYIO_SCURSOR:
+ default:
+ return -1; /* not implemented */
+
+ case WSDISPLAYIO_LINEBYTES:
+ if (scr != NULL)
+ *(u_int *)data = scr->rinfo.ri_stride;
+ else
+ *(u_int *)data = 0;
+ break;
+
+ }
+
+ if (res == EINVAL)
+ res = omdisplay_ioctl(v, cmd, data, flag, p);
+
+ return res;
+}
+
+void
+omdisplay_burner(void *v, u_int on, u_int flags)
+{
+
+ omdisplay_set_brightness(on ? omdisplay_get_brightness() : 0);
+
+ /* GPIO controls for appsliver */
+ if (on) {
+ omgpio_set_bit(93); /* 1 enable backlight */
+ omgpio_set_dir(93, OMGPIO_DIR_OUT);
+ omgpio_clear_bit(26); /* 0 enable LCD */
+ omgpio_set_dir(26, OMGPIO_DIR_OUT);
+ } else {
+ omgpio_clear_bit(93); /* 0 disable backlt */
+ omgpio_set_dir(93, OMGPIO_DIR_OUT);
+ omgpio_set_bit(26); /* 1 disable LCD */
+ omgpio_set_dir(26, OMGPIO_DIR_OUT);
+ }
+}
+
+int
+omdisplay_show_screen(void *v, void *cookie, int waitok,
+ void (*cb)(void *, int, int), void *cbarg)
+{
+ struct omdisplay_softc *sc = v;
+ struct rasops_info *ri = cookie;
+ struct omdisplay_screen *scr = ri->ri_hw, *old;
+
+ old = sc->sc_active;
+ if (old == scr)
+ return 0;
+
+ if (old != NULL)
+ ; /* Stop old screen */
+
+ sc->sc_active = scr;
+ omdisplay_initialize(sc, sc->sc_geometry);
+
+ /* Turn on LCD */
+ omdisplay_burner(v, 1, 0);
+
+ return (0);
+}
+
+
+
+/*
+ * wsdisplay I/O controls
+ */
+int
+omdisplay_param(struct omdisplay_softc *sc, ulong cmd,
+ struct wsdisplay_param *dp)
+{
+ int res = EINVAL;
+
+ switch (dp->param) {
+ case WSDISPLAYIO_PARAM_BACKLIGHT:
+ if (cmd == WSDISPLAYIO_GETPARAM) {
+ dp->min = 0;
+ dp->max = 1;
+ dp->curval = omdisplay_get_backlight();
+ res = 0;
+ } else if (cmd == WSDISPLAYIO_SETPARAM) {
+/* XXX */
+// omdisplay_set_backlight(dp->curval);
+ res = 0;
+ }
+ break;
+
+ case WSDISPLAYIO_PARAM_CONTRAST:
+ /* unsupported */
+ res = ENOTTY;
+ break;
+
+ case WSDISPLAYIO_PARAM_BRIGHTNESS:
+ if (cmd == WSDISPLAYIO_GETPARAM) {
+ dp->min = 1;
+ dp->max = omdisplay_max_brightness();
+ dp->curval = omdisplay_get_brightness();
+ res = 0;
+ } else if (cmd == WSDISPLAYIO_SETPARAM) {
+/* XXX */
+// omdisplay_set_brightness(dp->curval);
+ res = 0;
+ }
+ break;
+ }
+
+ return res;
+}
+
+
+/*
+ * LCD backlight
+ */
+
+static int lcdbrightnesscurval = 1;
+static int lcdislit = 1;
+static int lcdisblank = 0;
+
+struct lcd_backlight {
+ int duty; /* LZ9JG18 DAC value */
+ int cont; /* BACKLIGHT_CONT signal */
+ int on; /* BACKLIGHT_ON signal */
+};
+
+const struct lcd_backlight lcd_bl[] = {
+ { 0x00, 0, 0 }, /* 0: Off */
+ { 0x00, 0, 1 }, /* 1: 0% */
+ { 0x01, 0, 1 }, /* 2: 20% */
+ { 0x07, 0, 1 }, /* 3: 40% */
+ { 0x01, 1, 1 }, /* 4: 60% */
+ { 0x07, 1, 1 }, /* 5: 80% */
+ { 0x11, 1, 1 }, /* 6: 100% */
+ { -1, -1, -1 } /* 7: Invalid */
+};
+#define CURRENT_BACKLIGHT lcd_bl
+
+int
+omdisplay_max_brightness(void)
+{
+ int i;
+
+ for (i = 0; CURRENT_BACKLIGHT[i].duty != -1; i++)
+ ;
+ return i - 1;
+}
+
+int
+omdisplay_get_brightness(void)
+{
+
+ return lcdbrightnesscurval;
+}
+
+void
+omdisplay_set_brightness(int newval)
+{
+ int max;
+
+ max = omdisplay_max_brightness();
+ if (newval < 0)
+ newval = 0;
+ else if (newval > max)
+ newval = max;
+
+ if (omdisplay_get_backlight() && !lcdisblank)
+ omdisplay_set_brightness_internal(newval);
+
+ if (newval > 0)
+ lcdbrightnesscurval = newval;
+}
+
+void
+omdisplay_set_brightness_internal(int newval)
+{
+ static int curval = 1;
+ int i;
+
+ /*
+ * It appears that the C3000 backlight can draw too much power if we
+ * switch it from a low to a high brightness. Increasing brightness
+ * in steps avoids this issue.
+ */
+ if (newval > curval) {
+ for (i = curval + 1; i <= newval; i++) {
+/* atlas controls */
+ /* CURRENT_BACKLIGHT[newval].duty); */
+ }
+ } else {
+/* atlas controls */
+ /* CURRENT_BACKLIGHT[newval].duty); */
+ }
+
+ curval = newval;
+}
+
+int
+omdisplay_get_backlight(void)
+{
+
+ return lcdislit;
+}
+
+void
+omdisplay_set_backlight(int on)
+{
+
+ if (!on) {
+ omdisplay_set_brightness(0);
+ lcdislit = 0;
+ } else {
+ lcdislit = 1;
+ omdisplay_set_brightness(omdisplay_get_brightness());
+ }
+}
+
+void
+omdisplay_blank(int blank)
+{
+
+ if (blank) {
+ omdisplay_set_brightness(0);
+ lcdisblank = 1;
+ } else {
+ lcdisblank = 0;
+ omdisplay_set_brightness(omdisplay_get_brightness());
+ }
+}
+
+void
+omdisplay_suspend(struct omdisplay_softc *sc)
+{
+ if (sc->sc_active != NULL) {
+ omdisplay_stop(sc);
+ /* XXX disable clocks */
+ }
+}
+
+void
+omdisplay_resume(struct omdisplay_softc *sc)
+{
+ if (sc->sc_active != NULL) {
+ /* XXX - clocks? */
+ omdisplay_initialize(sc, sc->sc_geometry);
+ omdisplay_start(sc);
+ }
+}
+
+void
+omdisplay_activate(struct device *self, int act)
+{
+ struct omdisplay_softc *sc = (struct omdisplay_softc *)self;
+
+ switch (act) {
+ case DVACT_SUSPEND:
+ omdisplay_set_brightness(0);
+ omdisplay_suspend(sc);
+ break;
+ case DVACT_RESUME:
+ omdisplay_resume(sc);
+ omdisplay_set_brightness(omdisplay_get_brightness());
+ break;
+ }
+ return 0;
+}
+
+void
+omdisplay_initialize(struct omdisplay_softc *sc,
+ struct omdisplay_panel_data *geom)
+{
+ struct omdisplay_screen *scr;
+ u_int32_t reg;
+ u_int32_t mode;
+#if 0
+ int den, nom; /* pixel rate */
+#endif
+
+
+ reg = bus_space_read_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONTROL);
+
+ scr = sc->sc_active;
+
+ if (reg & (DISPC_CONTROL_LCDENABLE|DISPC_CONTROL_DIGITALENABLE)) {
+ omdisplay_stop(sc);
+ }
+
+ /* XXX - enable clocks */
+
+ /* disable all interrupts */
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_IRQENABLE, 0);
+
+ /* GPIOs ? */
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONFIG,
+ DISPC_CONFIG_LOADMODE_PG|DISPC_CONFIG_LOADMODE_DATA);
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DEFAULT_COLOR0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DEFAULT_COLOR1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_TRANS_COLOR0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_TRANS_COLOR1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_LINE_NUMBER, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DATA_CYCLE1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DATA_CYCLE2, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DATA_CYCLE3, 0);
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_SYSCONFIG,
+ DISPC_SYSCONFIG_SIDLEMODE_NONE|
+ DISPC_SYSCONFIG_MIDLEMODE_NONE);
+
+#if 0
+ if (geom->panel_flags & LCDPANEL_TDM) {
+ nom = tdmflags >>8 & 0x3;
+ den = tdmflags & 0x3;
+ } else {
+ nom = 1;
+ den = 1;
+ }
+ hsync = geom->width*den/nom + geom->horiz_sync_width +
+ geom->horiz_front_porch + geom->horiz_back_porch;
+#endif
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_TIMING_H,
+ DISPC_TIMING_H_HSW_s(geom->horiz_sync_width) |
+ DISPC_TIMING_H_HFP_s(geom->horiz_front_porch) |
+ DISPC_TIMING_H_HBP_s(geom->horiz_back_porch));
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_TIMING_V,
+ DISPC_TIMING_V_VSW_s(geom->vert_sync_width) |
+ DISPC_TIMING_V_VFP_s(geom->vert_front_porch) |
+ DISPC_TIMING_V_VBP_s(geom->vert_back_porch));
+
+ reg = 0;
+ if (geom->sync & PANEL_SYNC_H_ACTIVE_HIGH)
+ reg |= DISPC_POL_FREQ_IHS;
+ if (geom->sync & PANEL_SYNC_V_ACTIVE_HIGH)
+ reg |= DISPC_POL_FREQ_IVS;
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_POL_FREQ, reg);
+
+
+ /* clkdiv = pixclock/period; */
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_SIZE_LCD,
+ DISPC_SIZE_LCD_PPL_s(geom->width-1) |
+ DISPC_SIZE_LCD_LPP_s(geom->height-1));
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_SIZE_DIG,
+ DISPC_SIZE_LCD_PPL_s(geom->width-1) |
+ DISPC_SIZE_LCD_LPP_s(geom->height-1));
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_SIZE,
+ DISPC_GFX_SIZE_X_s(geom->width-1) |
+ DISPC_GFX_SIZE_Y_s(geom->height-1));
+
+
+ /* XXX!!! */
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_DIVISOR,
+ DISPC_DIVISOR_LCD_s(1) | DISPC_DIVISOR_PCD_s(6));
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_BA0,
+ scr->segs[0].ds_addr);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_BA1,
+ scr->segs[0].ds_addr);
+
+ /* non-rotated */
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_PIXEL_INC, 1);
+
+
+ /* XXX 24bit -> 32 pixels */
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_ROW_INC,
+ 1 + scr->rinfo.ri_stride -
+ (scr->rinfo.ri_width * scr->rinfo.ri_depth / 8));
+
+ switch (geom->depth) {
+ case 1:
+ mode = DISPC_GFX_ATTRIBUTES_GFXFMT_1;
+ break;
+ case 2:
+ mode = DISPC_GFX_ATTRIBUTES_GFXFMT_2;
+ break;
+ case 4:
+ mode = DISPC_GFX_ATTRIBUTES_GFXFMT_4;
+ break;
+ case 8:
+ mode = DISPC_GFX_ATTRIBUTES_GFXFMT_8;
+ break;
+ case 12:
+ mode = DISPC_GFX_ATTRIBUTES_GFXFMT_12;
+ break;
+ case 16:
+ mode = DISPC_GFX_ATTRIBUTES_GFXFMT_16;
+ break;
+ case 24:
+ mode = DISPC_GFX_ATTRIBUTES_GFXFMT_24;
+ break;
+ default:
+ panic("invalid depth %d", geom->depth);
+ }
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_ATTRIBUTES,
+ DISPC_GFX_ATTRIBUTES_GFXENABLE | mode |
+ DISPC_GFX_ATTRIBUTES_BURST_8);
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_POSITION, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_WINDOW_SKIP, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_FIFO_THRESHOLD,
+ (0xfc << DISPC_GFX_FIFO_THRESHOLD_HIGH_SHIFT) |
+ (0xc0 << DISPC_GFX_FIFO_THRESHOLD_LOW_SHIFT));
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_ROW_INC, 1);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_PIXEL_INC, 1);
+
+ /* DISPC_CONFIG_PALETTEGAMMA not enabled */
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_GFX_TABLE_BA,
+ scr->segs[0].ds_addr);
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_BA0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_BA1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_SIZE, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_ATTRIBUTES, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIFO_THRESHOLD,
+ 0xc00040); /* XXX */
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIFO_SIZE_STATUS,
+ 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_ROW_INC, 1);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_PIXEL_INC, 1);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_PICTURE_SIZE, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_ACCU0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_ACCU1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H2, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H3, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H4, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H5, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H6, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_H7, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV2, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV3, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV4, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV5, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV6, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_FIR_COEF_HV7, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF2, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF3, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID1_CONV_COEF4, 0);
+
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_BA0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_BA1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_SIZE, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_ATTRIBUTES, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIFO_THRESHOLD,
+ 0xc00040); /* XXX */
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIFO_SIZE_STATUS,
+ 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_ROW_INC, 1);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_PIXEL_INC, 1);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_PICTURE_SIZE, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_ACCU0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_ACCU1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H2, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H3, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H4, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H5, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H6, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_H7, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV2, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV3, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV4, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV5, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV6, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_FIR_COEF_HV7, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF0, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF1, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF2, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF3, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_VID2_CONV_COEF4, 0);
+
+ omdisplay_start(sc);
+}
+
+void
+omdisplay_setup_rasops(struct omdisplay_softc *sc, struct rasops_info *rinfo)
+{
+ struct omdisplay_wsscreen_descr *descr;
+ struct omdisplay_panel_data *geom;
+
+ descr = &omdisplay_screen;
+ geom = sc->sc_geometry;
+
+ rinfo->ri_flg = descr->flags;
+ rinfo->ri_depth = descr->depth;
+ rinfo->ri_width = geom->width;
+ rinfo->ri_height = geom->height;
+ rinfo->ri_stride = geom->linebytes;
+
+ /* pixel position */
+ if (descr->depth == 16) {
+ rinfo->ri_rnum = 5;
+ rinfo->ri_rpos = 11;
+ rinfo->ri_gnum = 6;
+ rinfo->ri_gpos = 5;
+ rinfo->ri_bnum = 5;
+ rinfo->ri_bpos = 0;
+ }
+
+ if (descr->c.nrows == 0) {
+ /* get rasops to compute screen size the first time */
+ rasops_init(rinfo, 100, 100);
+ } else {
+ if (descr->flags != 0) /* rotate */
+ rasops_init(rinfo, descr->c.ncols, descr->c.nrows);
+ else
+ rasops_init(rinfo, descr->c.nrows, descr->c.ncols);
+ }
+
+ descr->c.nrows = rinfo->ri_rows;
+ descr->c.ncols = rinfo->ri_cols;
+ descr->c.capabilities = rinfo->ri_caps;
+ descr->c.textops = &rinfo->ri_ops;
+
+}
+
+
+int
+omdisplay_alloc_screen(void *v, const struct wsscreen_descr *_type,
+ void **cookiep, int *curxp, int *curyp, long *attrp)
+{
+ struct omdisplay_softc *sc = v;
+ struct omdisplay_screen *scr;
+ struct rasops_info *ri;
+ struct omdisplay_wsscreen_descr *type =
+ (struct omdisplay_wsscreen_descr *)_type;
+ int error;
+
+ scr = malloc(sizeof *scr, M_DEVBUF, (cold ? M_NOWAIT : M_WAITOK));
+ if (scr == NULL)
+ return (ENOMEM);
+
+ error = omdisplay_new_screen(sc, scr, type->depth);
+ if (error != 0) {
+ free(scr, M_DEVBUF, 0);
+ return (error);
+ }
+
+ /*
+ * initialize raster operation for this screen.
+ */
+ ri = &scr->rinfo;
+ ri->ri_hw = (void *)scr;
+ ri->ri_bits = scr->buf_va;
+ omdisplay_setup_rasops(sc, ri);
+
+ /* assumes 16 bpp */
+ ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
+
+ *cookiep = ri;
+ *curxp = 0;
+ *curyp = 0;
+
+ return 0;
+}
+
+/*
+ * Create and initialize a new screen buffer.
+ */
+int
+omdisplay_new_screen(struct omdisplay_softc *sc,
+ struct omdisplay_screen *scr, int depth)
+{
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ bus_dma_tag_t dma_tag;
+ struct omdisplay_panel_data *geometry;
+ int width, height;
+ bus_size_t size;
+ int error, palette_size;
+ int busdma_flag = (cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
+
+ if (sc != NULL) {
+ iot = sc->sc_iot;
+ ioh = sc->sc_dcioh;
+ dma_tag = sc->sc_dma_tag;
+ geometry = sc->sc_geometry;
+ } else {
+ /* We are creating the console screen. */
+#if 0
+ iot = omdisplay_console.iot;
+ ioh = omdisplay_console.ioh;
+ dma_tag = omdisplay_console.dma_tag;
+ geometry = omdisplay_console.geometry;
+#endif
+ }
+
+ width = geometry->width;
+ height = geometry->height;
+ palette_size = 0;
+
+ switch (depth) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ palette_size = (1 << depth) * sizeof (uint16_t);
+ /* FALLTHROUGH */
+ case 16:
+ case 24:
+ size = geometry->height * geometry->linebytes;
+ break;
+ default:
+ printf("%s: Unknown depth (%d)\n",
+ sc != NULL ? sc->sc_dev.dv_xname : "console", depth);
+ return (EINVAL);
+ }
+
+ bzero(scr, sizeof *scr);
+
+ scr->nsegs = 0;
+ scr->depth = depth;
+ scr->buf_size = size;
+ scr->buf_va = NULL;
+ size = roundup(size, 16);
+#if 0
+ + 3 * sizeof (struct lcd_dma_descriptor)
+ + palette_size;
+#endif
+
+ error = bus_dmamem_alloc(dma_tag, size, 0x100000, 0,
+ scr->segs, 1, &(scr->nsegs), busdma_flag);
+ if (error != 0 || scr->nsegs != 1) {
+ /* XXX: Actually we can handle nsegs > 1 case by means
+ of multiple DMA descriptors for a panel. It would
+ make code here a bit hairy */
+ if (error == 0)
+ error = E2BIG;
+ goto bad;
+ }
+
+ error = bus_dmamem_map(dma_tag, scr->segs, scr->nsegs,
+ size, (caddr_t *)&(scr->buf_va), busdma_flag | BUS_DMA_COHERENT);
+ if (error != 0)
+ goto bad;
+
+ memset(scr->buf_va, 0, scr->buf_size);
+ bcopy(splash, scr->buf_va,
+ sizeof (splash) > scr->buf_size ? scr->buf_size : sizeof (splash));
+
+ /* map memory for DMA */
+ if (bus_dmamap_create(dma_tag, 1024 * 1024 * 2, 1,
+ 1024 * 1024 * 2, 0, busdma_flag, &scr->dma))
+ goto bad;
+ error = bus_dmamap_load(dma_tag, scr->dma,
+ scr->buf_va, size, NULL, busdma_flag);
+ if (error != 0) {
+ goto bad;
+ }
+
+ scr->map_size = size; /* used when unmap this. */
+
+ if (sc != NULL) {
+ LIST_INSERT_HEAD(&(sc->sc_screens), scr, link);
+ sc->sc_nscreens++;
+ }
+
+ omdisplay_initialize(sc, geometry);
+
+ return (0);
+
+ bad:
+ if (scr->buf_va)
+ bus_dmamem_unmap(dma_tag, scr->buf_va, size);
+ if (scr->nsegs)
+ bus_dmamem_free(dma_tag, scr->segs, scr->nsegs);
+ return (error);
+}
+paddr_t
+omdisplay_mmap(void *v, off_t offset, int prot)
+{
+ struct omdisplay_softc *sc = v;
+ struct omdisplay_screen *screen = sc->sc_active; /* ??? */
+
+ if ((offset & PAGE_MASK) != 0)
+ return (-1);
+
+ if (screen == NULL)
+ return (-1);
+
+ if (offset < 0 ||
+ offset >= screen->rinfo.ri_stride * screen->rinfo.ri_height)
+ return (-1);
+
+ return (bus_dmamem_mmap(sc->sc_dma_tag, screen->segs, screen->nsegs,
+ offset, prot, BUS_DMA_WAITOK | BUS_DMA_COHERENT));
+}
+
+void
+omdisplay_free_screen(void *v, void *cookie)
+{
+ struct omdisplay_softc *sc = v;
+ struct rasops_info *ri = cookie;
+ struct omdisplay_screen *scr = ri->ri_hw;
+
+ LIST_REMOVE(scr, link);
+ sc->sc_nscreens--;
+ if (scr == sc->sc_active) {
+ /* at first, we need to stop LCD DMA */
+ sc->sc_active = NULL;
+
+#ifdef DEBUG
+ printf("lcd_free on active screen\n");
+#endif
+
+ omdisplay_stop(sc);
+ }
+
+ if (scr->buf_va)
+ bus_dmamem_unmap(sc->sc_dma_tag, scr->buf_va, scr->map_size);
+
+ if (scr->nsegs > 0)
+ bus_dmamem_free(sc->sc_dma_tag, scr->segs, scr->nsegs);
+
+ free(scr, M_DEVBUF, 0);
+}
+
+int
+omdisplay_load_font(void *v, void *emulcookie, struct wsdisplay_font *font)
+{
+ struct omdisplay_softc *sc = v;
+ struct omdisplay_screen *scr = sc->sc_active;
+
+ if (scr == NULL)
+ return ENXIO;
+
+ return rasops_load_font(scr->rinfo, emulcookie, font);
+}
+
+int
+omdisplay_list_font(void *v, struct wsdisplay_font *font)
+{
+ struct omdisplay_softc *sc = v;
+ struct omdisplay_screen *scr = sc->sc_active;
+
+ if (scr == NULL)
+ return ENXIO;
+
+ return rasops_list_font(scr->rinfo, font);
+}
+
+void
+omdisplay_start(struct omdisplay_softc *sc)
+{
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONTROL,
+ DISPC_CONTROL_GPOUT0 | DISPC_CONTROL_GPOUT1 |
+ DISPC_CONTROL_TFTDATALINES_18 /*XXX 18? */ |
+ DISPC_CONTROL_STNTFT |
+ DISPC_CONTROL_GOLCD |
+ DISPC_CONTROL_LCDENABLE);
+}
+
+void
+omdisplay_stop(struct omdisplay_softc *sc)
+{
+ bus_space_write_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONTROL,
+ bus_space_read_4(sc->sc_iot, sc->sc_dcioh, DISPC_CONTROL) &
+ ~(DISPC_CONTROL_DIGITALENABLE|DISPC_CONTROL_LCDENABLE));
+
+ /* XXX - wait for end of frame? */
+}
+
+int
+omdisplay_intr(void *v)
+{
+ /* XXX */
+ return 1;
+}
+
--- /dev/null
+/* $OpenBSD: omdog.c,v 1.5 2014/12/10 12:27:56 mikeb Exp $ */
+/*
+ * Copyright (c) 2013 Federico G. Schwindt <fgsch@openbsd.org>
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/evcount.h>
+#include <sys/socket.h>
+#include <sys/timeout.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <armv7/armv7/armv7var.h>
+
+#define WIDR 0x00 /* Identification Register */
+#define WCLR 0x24 /* Control Register */
+#define WCLR_PRE (1 << 5)
+#define WCLR_PTV (0 << 2)
+#define WCRR 0x28 /* Counter Register */
+#define WLDR 0x2c /* Load Register */
+#define WTGR 0x30 /* Trigger Register */
+#define WWPS 0x34 /* Write Posting Bits Reg. */
+#define WWPS_WSPR (1 << 4)
+#define WWPS_WTGR (1 << 3)
+#define WWPS_WLDR (1 << 2)
+#define WWPS_WCRR (1 << 1)
+#define WWPS_WCLR (1 << 0)
+#define WSPR 0x48 /* Start/Stop Register */
+
+#define OMDOG_VAL(secs) (0xffffffff - ((secs) * (32768 / (1 << 0))) + 1)
+
+
+struct omdog_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ int sc_period;
+};
+
+struct omdog_softc *omdog_sc;
+
+void omdog_attach(struct device *, struct device *, void *);
+int omdog_activate(struct device *, int);
+void omdog_start(struct omdog_softc *);
+void omdog_stop(struct omdog_softc *);
+void omdog_sync(struct omdog_softc *);
+int omdog_cb(void *, int);
+void omdog_reset(void);
+
+struct cfattach omdog_ca = {
+ sizeof (struct omdog_softc), NULL, omdog_attach, NULL, omdog_activate
+};
+
+struct cfdriver omdog_cd = {
+ NULL, "omdog", DV_DULL
+};
+
+void
+omdog_attach(struct device *parent, struct device *self, void *args)
+{
+ struct armv7_attach_args *aa = args;
+ struct omdog_softc *sc = (struct omdog_softc *) self;
+ u_int32_t rev;
+
+ sc->sc_iot = aa->aa_iot;
+ if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
+ panic("%s: bus_space_map failed!", __func__);
+
+ rev = bus_space_read_4(sc->sc_iot, sc->sc_ioh, WIDR);
+
+ printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
+ omdog_sc = sc;
+
+ omdog_stop(sc);
+
+#ifndef SMALL_KERNEL
+ wdog_register(omdog_cb, sc);
+#endif
+}
+
+int
+omdog_activate(struct device *self, int act)
+{
+ switch (act) {
+ case DVACT_POWERDOWN:
+#ifndef SMALL_KERNEL
+ wdog_shutdown(self);
+#endif
+ break;
+ }
+
+ return (0);
+}
+
+void
+omdog_start(struct omdog_softc *sc)
+{
+ /* Write the enable sequence data BBBBh followed by 4444h */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0xbbbb);
+ omdog_sync(sc);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0x4444);
+ omdog_sync(sc);
+}
+
+void
+omdog_stop(struct omdog_softc *sc)
+{
+ /* Write the disable sequence data AAAAh followed by 5555h */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0xaaaa);
+ omdog_sync(sc);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0x5555);
+ omdog_sync(sc);
+}
+
+void
+omdog_sync(struct omdog_softc *sc)
+{
+ while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, WWPS) &
+ (WWPS_WSPR|WWPS_WTGR|WWPS_WLDR|WWPS_WCRR|WWPS_WCLR))
+ delay(10);
+}
+
+int
+omdog_cb(void *self, int period)
+{
+ struct omdog_softc *sc = self;
+
+ if (sc->sc_period != 0 && sc->sc_period != period)
+ omdog_stop(sc);
+
+ if (period != 0) {
+ if (sc->sc_period != period) {
+ /* Set the prescaler */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, WCLR,
+ (WCLR_PRE|WCLR_PTV));
+
+ /* Set the reload counter */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, WLDR,
+ OMDOG_VAL(period));
+ }
+
+ omdog_sync(sc);
+
+ /* Trigger the reload */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, WTGR,
+ ~bus_space_read_4(sc->sc_iot, sc->sc_ioh, WTGR));
+
+ if (sc->sc_period != period)
+ omdog_start(sc);
+ }
+
+ sc->sc_period = period;
+
+ return (period);
+}
+
+void
+omdog_reset(void)
+{
+ if (omdog_sc == NULL)
+ return;
+
+ if (omdog_sc->sc_period != 0)
+ omdog_stop(omdog_sc);
+
+ bus_space_write_4(omdog_sc->sc_iot, omdog_sc->sc_ioh, WCRR,
+ 0xffffff80);
+
+ omdog_start(omdog_sc);
+
+ delay(100000);
+}
--- /dev/null
+/* $OpenBSD: omehci.c,v 1.3 2014/05/19 13:11:31 mpi Exp $ */
+
+/*
+ * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray@gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/rwlock.h>
+#include <sys/timeout.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/prcmvar.h>
+#include <armv7/omap/omgpiovar.h>
+#include <armv7/omap/omehcivar.h>
+
+#include <dev/usb/ehcireg.h>
+#include <dev/usb/ehcivar.h>
+
+void omehci_attach(struct device *, struct device *, void *);
+int omehci_detach(struct device *, int);
+int omehci_activate(struct device *, int);
+
+struct omehci_softc {
+ struct ehci_softc sc;
+ void *sc_ih;
+ bus_space_handle_t uhh_ioh;
+ bus_space_handle_t tll_ioh;
+
+ uint32_t ehci_rev;
+ uint32_t tll_avail;
+
+ uint32_t port_mode[OMAP_HS_USB_PORTS];
+ uint32_t phy_reset[OMAP_HS_USB_PORTS];
+ uint32_t reset_gpio_pin[OMAP_HS_USB_PORTS];
+
+ void (*early_init)(void);
+};
+
+int omehci_init(struct omehci_softc *);
+void omehci_soft_phy_reset(struct omehci_softc *sc, unsigned int port);
+void omehci_enable(struct omehci_softc *);
+void omehci_disable(struct omehci_softc *);
+void omehci_utmi_init(struct omehci_softc *sc, unsigned int en_mask);
+void misc_setup(struct omehci_softc *sc);
+void omehci_phy_reset(uint32_t on, uint32_t _delay);
+void omehci_uhh_init(struct omehci_softc *sc);
+void omehci_v4_early_init(void);
+
+struct cfattach omehci_ca = {
+ sizeof (struct omehci_softc), NULL, omehci_attach,
+ omehci_detach, omehci_activate
+};
+
+void
+omehci_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct omehci_softc *sc = (struct omehci_softc *)self;
+ struct armv7_attach_args *aa = aux;
+ usbd_status r;
+ char *devname = sc->sc.sc_bus.bdev.dv_xname;
+ uint32_t i;
+
+ sc->sc.iot = aa->aa_iot;
+ sc->sc.sc_bus.dmatag = aa->aa_dmat;
+ sc->sc.sc_size = aa->aa_dev->mem[0].size;
+
+ /* set defaults */
+ for (i = 0; i < 3; i++) {
+ sc->phy_reset[i] = 0;
+ sc->port_mode[i] = EHCI_HCD_OMAP_MODE_UNKNOWN;
+ sc->reset_gpio_pin[i] = -1;
+ }
+
+ switch (board_id)
+ {
+ case BOARD_ID_OMAP4_PANDA:
+ sc->tll_avail = 0;
+ sc->port_mode[0] = EHCI_HCD_OMAP_MODE_PHY;
+ sc->early_init = omehci_v4_early_init;
+ break;
+ default:
+ break;
+ }
+
+ /* Map I/O space */
+ if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc.ioh)) {
+ printf(": cannot map mem space\n");
+ goto out;
+ }
+
+ if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[1].addr,
+ aa->aa_dev->mem[1].size, 0, &sc->uhh_ioh)) {
+ printf(": cannot map mem space\n");
+ goto mem0;
+ }
+
+ if (sc->tll_avail &&
+ bus_space_map(sc->sc.iot, aa->aa_dev->mem[2].addr,
+ aa->aa_dev->mem[2].size, 0, &sc->tll_ioh)) {
+ printf(": cannot map mem space\n");
+ goto mem1;
+ }
+
+ printf("\n");
+
+ if (sc->early_init)
+ sc->early_init();
+
+ if (omehci_init(sc))
+ return;
+
+ /* Disable interrupts, so we don't get any spurious ones. */
+ sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
+ EOWRITE2(&sc->sc, EHCI_USBINTR, 0);
+
+ sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_USB,
+ ehci_intr, &sc->sc, devname);
+ if (sc->sc_ih == NULL) {
+ printf(": unable to establish interrupt\n");
+ printf("XXX - disable ehci and prcm");
+ goto mem2;
+ }
+
+ strlcpy(sc->sc.sc_vendor, "TI OMAP", sizeof(sc->sc.sc_vendor));
+ r = ehci_init(&sc->sc);
+ if (r != USBD_NORMAL_COMPLETION) {
+ printf("%s: init failed, error=%d\n", devname, r);
+ printf("XXX - disable ehci and prcm");
+ goto intr;
+ }
+
+ config_found(self, &sc->sc.sc_bus, usbctlprint);
+
+ goto out;
+
+intr:
+ arm_intr_disestablish(sc->sc_ih);
+ sc->sc_ih = NULL;
+mem2:
+ bus_space_unmap(sc->sc.iot, sc->tll_ioh, aa->aa_dev->mem[2].size);
+mem1:
+ bus_space_unmap(sc->sc.iot, sc->uhh_ioh, aa->aa_dev->mem[1].size);
+mem0:
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ sc->sc.sc_size = 0;
+out:
+ return;
+}
+
+int
+omehci_init(struct omehci_softc *sc)
+{
+ uint32_t i = 0, reg;
+ uint32_t reset_performed = 0;
+ uint32_t timeout = 0;
+ uint32_t tll_ch_mask = 0;
+
+ /* enable high speed usb host clock */
+ prcm_enablemodule(PRCM_USB);
+
+ /* Hold the PHY in reset while configuring */
+ for (i = 0; i < OMAP_HS_USB_PORTS; i++) {
+ if (sc->phy_reset[i]) {
+ /* Configure the GPIO to drive low (hold in reset) */
+ if (sc->reset_gpio_pin[i] != -1) {
+ omgpio_set_dir(sc->reset_gpio_pin[i],
+ OMGPIO_DIR_OUT);
+ omgpio_clear_bit(sc->reset_gpio_pin[i]);
+ reset_performed = 1;
+ }
+ }
+ }
+
+ /* Hold the PHY in RESET for enough time till DIR is high */
+ if (reset_performed)
+ delay(10);
+
+ /* Read the UHH revision */
+ sc->ehci_rev = bus_space_read_4(sc->sc.iot, sc->uhh_ioh,
+ OMAP_USBHOST_UHH_REVISION);
+
+ /* Initilise the low level interface module(s) */
+ if (sc->ehci_rev == OMAP_EHCI_REV1) {
+ /* Enable the USB TLL */
+ prcm_enablemodule(PRCM_USBTLL);
+
+ /* Perform TLL soft reset, and wait until reset is complete */
+ bus_space_write_4(sc->sc.iot, sc->tll_ioh,
+ OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_SOFTRESET);
+
+ /* Set the timeout to 100ms*/
+ timeout = (hz < 10) ? 1 : ((100 * hz) / 1000);
+
+ /* Wait for TLL reset to complete */
+ while ((bus_space_read_4(sc->sc.iot, sc->tll_ioh,
+ OMAP_USBTLL_SYSSTATUS) & TLL_SYSSTATUS_RESETDONE)
+ == 0x00) {
+
+ /* Sleep for a tick */
+ delay(10);
+
+ if (timeout-- == 0) {
+ return 1;
+ }
+ }
+
+ bus_space_write_4(sc->sc.iot, sc->tll_ioh,
+ OMAP_USBTLL_SYSCONFIG,
+ TLL_SYSCONFIG_ENAWAKEUP | TLL_SYSCONFIG_AUTOIDLE |
+ TLL_SYSCONFIG_SIDLE_SMART_IDLE | TLL_SYSCONFIG_CACTIVITY);
+ } else if (sc->ehci_rev == OMAP_EHCI_REV2) {
+ /* For OMAP44xx devices you have to enable the per-port clocks:
+ * PHY_MODE - External ULPI clock
+ * TTL_MODE - Internal UTMI clock
+ * HSIC_MODE - Internal 480Mhz and 60Mhz clocks
+ */
+ if (sc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) {
+ //ti_prcm_clk_set_source(USBP1_PHY_CLK, EXT_CLK);
+ prcm_enablemodule(PRCM_USBP1_PHY);
+ } else if (sc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
+ prcm_enablemodule(PRCM_USBP1_UTMI);
+ else if (sc->port_mode[0] == EHCI_HCD_OMAP_MODE_HSIC)
+ prcm_enablemodule(PRCM_USBP1_HSIC);
+
+ if (sc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) {
+ //ti_prcm_clk_set_source(USBP2_PHY_CLK, EXT_CLK);
+ prcm_enablemodule(PRCM_USBP2_PHY);
+ } else if (sc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
+ prcm_enablemodule(PRCM_USBP2_UTMI);
+ else if (sc->port_mode[1] == EHCI_HCD_OMAP_MODE_HSIC)
+ prcm_enablemodule(PRCM_USBP2_HSIC);
+ }
+
+ /* Put UHH in SmartIdle/SmartStandby mode */
+ reg = bus_space_read_4(sc->sc.iot, sc->uhh_ioh,
+ OMAP_USBHOST_UHH_SYSCONFIG);
+ if (sc->ehci_rev == OMAP_EHCI_REV1) {
+ reg &= ~(UHH_SYSCONFIG_SIDLEMODE_MASK |
+ UHH_SYSCONFIG_MIDLEMODE_MASK);
+ reg |= (UHH_SYSCONFIG_ENAWAKEUP |
+ UHH_SYSCONFIG_AUTOIDLE |
+ UHH_SYSCONFIG_CLOCKACTIVITY |
+ UHH_SYSCONFIG_SIDLEMODE_SMARTIDLE |
+ UHH_SYSCONFIG_MIDLEMODE_SMARTSTANDBY);
+ } else if (sc->ehci_rev == OMAP_EHCI_REV2) {
+ reg &= ~UHH_SYSCONFIG_IDLEMODE_MASK;
+ reg |= UHH_SYSCONFIG_IDLEMODE_NOIDLE;
+ reg &= ~UHH_SYSCONFIG_STANDBYMODE_MASK;
+ reg |= UHH_SYSCONFIG_STANDBYMODE_NOSTDBY;
+ }
+ bus_space_write_4(sc->sc.iot, sc->uhh_ioh, OMAP_USBHOST_UHH_SYSCONFIG,
+ reg);
+
+ reg = bus_space_read_4(sc->sc.iot, sc->uhh_ioh,
+ OMAP_USBHOST_UHH_HOSTCONFIG);
+
+ /* Setup ULPI bypass and burst configurations */
+ reg |= (UHH_HOSTCONFIG_ENA_INCR4 |
+ UHH_HOSTCONFIG_ENA_INCR8 |
+ UHH_HOSTCONFIG_ENA_INCR16);
+ reg &= ~UHH_HOSTCONFIG_ENA_INCR_ALIGN;
+
+ if (sc->ehci_rev == OMAP_EHCI_REV1) {
+ if (sc->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
+ reg &= ~UHH_HOSTCONFIG_P1_CONNECT_STATUS;
+ if (sc->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
+ reg &= ~UHH_HOSTCONFIG_P2_CONNECT_STATUS;
+ if (sc->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
+ reg &= ~UHH_HOSTCONFIG_P3_CONNECT_STATUS;
+
+ /* Bypass the TLL module for PHY mode operation */
+ if ((sc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ||
+ (sc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ||
+ (sc->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY))
+ reg &= ~UHH_HOSTCONFIG_P1_ULPI_BYPASS;
+ else
+ reg |= UHH_HOSTCONFIG_P1_ULPI_BYPASS;
+ } else if (sc->ehci_rev == OMAP_EHCI_REV2) {
+ reg |= UHH_HOSTCONFIG_APP_START_CLK;
+
+ /* Clear port mode fields for PHY mode*/
+ reg &= ~UHH_HOSTCONFIG_P1_MODE_MASK;
+ reg &= ~UHH_HOSTCONFIG_P2_MODE_MASK;
+
+ if (sc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
+ reg |= UHH_HOSTCONFIG_P1_MODE_UTMI_PHY;
+ else if (sc->port_mode[0] == EHCI_HCD_OMAP_MODE_HSIC)
+ reg |= UHH_HOSTCONFIG_P1_MODE_HSIC;
+
+ if (sc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
+ reg |= UHH_HOSTCONFIG_P2_MODE_UTMI_PHY;
+ else if (sc->port_mode[1] == EHCI_HCD_OMAP_MODE_HSIC)
+ reg |= UHH_HOSTCONFIG_P2_MODE_HSIC;
+ }
+
+ bus_space_write_4(sc->sc.iot, sc->uhh_ioh, OMAP_USBHOST_UHH_HOSTCONFIG, reg);
+
+ /* If any of the ports are configured in TLL mode, enable them */
+ for (i = 0; i < OMAP_HS_USB_PORTS; i++)
+ if (sc->port_mode[i] == EHCI_HCD_OMAP_MODE_PHY)
+ tll_ch_mask |= 1 << i;
+
+ /* Enable UTMI mode for required TLL channels */
+#ifdef notyet
+ if (tll_ch_mask)
+ omap_ehci_utmi_init(sc, tll_ch_mask);
+#endif
+
+ /* Release the PHY reset signal now we have configured everything */
+ if (reset_performed) {
+ /* Delay for 10ms */
+ delay(10000);
+
+ /* Release reset */
+ for (i = 0; i < 3; i++) {
+ if (sc->phy_reset[i] && (sc->reset_gpio_pin[i] != -1))
+ omgpio_set_bit(sc->reset_gpio_pin[i]);
+ }
+ }
+
+ /* Set the interrupt threshold control, it controls the maximum rate at
+ * which the host controller issues interrupts. We set it to 1 microframe
+ * at startup - the default is 8 mircoframes (equates to 1ms).
+ */
+ reg = bus_space_read_4(sc->sc.iot, sc->sc.ioh, OMAP_USBHOST_USBCMD);
+ reg &= 0xff00ffff;
+ reg |= (1 << 16);
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, OMAP_USBHOST_USBCMD, reg);
+
+ /* Soft reset the PHY using PHY reset command over ULPI */
+ for (i = 0; i < OMAP_HS_USB_PORTS; i++)
+ if (sc->port_mode[i] == EHCI_HCD_OMAP_MODE_PHY)
+ omehci_soft_phy_reset(sc, i);
+
+ return(0);
+}
+
+void
+omehci_soft_phy_reset(struct omehci_softc *sc, unsigned int port)
+{
+ unsigned long timeout = (hz < 10) ? 1 : ((100 * hz) / 1000);
+ uint32_t reg;
+
+ reg = ULPI_FUNC_CTRL_RESET
+ /* FUNCTION_CTRL_SET register */
+ | (ULPI_SET(ULPI_FUNC_CTRL) << OMAP_USBHOST_INSNREG05_ULPI_REGADD_SHIFT)
+ /* Write */
+ | (2 << OMAP_USBHOST_INSNREG05_ULPI_OPSEL_SHIFT)
+ /* PORTn */
+ | ((port + 1) << OMAP_USBHOST_INSNREG05_ULPI_PORTSEL_SHIFT)
+ /* start ULPI access*/
+ | (1 << OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT);
+
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, OMAP_USBHOST_INSNREG05_ULPI, reg);
+
+ timeout += 1000000;
+ /* Wait for ULPI access completion */
+ while ((bus_space_read_4(sc->sc.iot, sc->sc.ioh, OMAP_USBHOST_INSNREG05_ULPI)
+ & (1 << OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT))) {
+
+ /* Sleep for a tick */
+ delay(10);
+
+ if (timeout-- == 0) {
+ printf("PHY reset operation timed out\n");
+ break;
+ }
+ }
+}
+
+int
+omehci_detach(struct device *self, int flags)
+{
+ struct omehci_softc *sc = (struct omehci_softc *)self;
+ int rv;
+
+ rv = ehci_detach(self, flags);
+ if (rv)
+ return (rv);
+
+ if (sc->sc_ih != NULL) {
+ arm_intr_disestablish(sc->sc_ih);
+ sc->sc_ih = NULL;
+ }
+
+ if (sc->sc.sc_size) {
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ sc->sc.sc_size = 0;
+ }
+
+ /* XXX: stop clock */
+
+ return (0);
+}
+
+int
+omehci_activate(struct device *self, int act)
+{
+ struct omehci_softc *sc = (struct omehci_softc *)self;
+
+ switch (act) {
+ case DVACT_SUSPEND:
+ sc->sc.sc_bus.use_polling++;
+ /* FIXME */
+ sc->sc.sc_bus.use_polling--;
+ break;
+ case DVACT_RESUME:
+ sc->sc.sc_bus.use_polling++;
+ /* FIXME */
+ sc->sc.sc_bus.use_polling--;
+ break;
+ case DVACT_POWERDOWN:
+ ehci_reset(&sc->sc);
+ break;
+ }
+ return 0;
+}
+
+void
+omehci_v4_early_init()
+{
+ omgpio_set_dir(1, OMGPIO_DIR_OUT);
+ omgpio_clear_bit(1);
+ omgpio_set_dir(62, OMGPIO_DIR_OUT);
+ omgpio_clear_bit(62);
+
+ /* wait for power down */
+ delay(1000);
+
+ omgpio_set_bit(1);
+ omgpio_set_bit(62);
+
+ /* wait until powered up */
+ delay(1000);
+}
--- /dev/null
+/* $OpenBSD: omehcivar.h,v 1.1 2013/09/04 14:38:31 patrick Exp $ */
+
+/*
+ * Misc
+ */
+#define OMAP_HS_USB_PORTS 3
+
+/*
+ * USB TTL Module
+ */
+#define OMAP_USBTLL_REVISION 0x0000
+#define OMAP_USBTLL_SYSCONFIG 0x0010
+#define OMAP_USBTLL_SYSSTATUS 0x0014
+#define OMAP_USBTLL_IRQSTATUS 0x0018
+#define OMAP_USBTLL_IRQENABLE 0x001C
+#define OMAP_USBTLL_TLL_SHARED_CONF 0x0030
+#define OMAP_USBTLL_TLL_CHANNEL_CONF(i) (0x0040 + (0x04 * (i)))
+#define OMAP_USBTLL_SAR_CNTX(i) (0x0400 + (0x04 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_ID_LO(i) (0x0800 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_ID_HI(i) (0x0801 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_PRODUCT_ID_LO(i) (0x0802 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_PRODUCT_ID_HI(i) (0x0803 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_FUNCTION_CTRL(i) (0x0804 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_FUNCTION_CTRL_SET(i) (0x0805 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_FUNCTION_CTRL_CLR(i) (0x0806 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_INTERFACE_CTRL(i) (0x0807 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_INTERFACE_CTRL_SET(i) (0x0808 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_INTERFACE_CTRL_CLR(i) (0x0809 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_OTG_CTRL(i) (0x080A + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_OTG_CTRL_SET(i) (0x080B + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_OTG_CTRL_CLR(i) (0x080C + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_RISE(i) (0x080D + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_RISE_SET(i) (0x080E + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_RISE_CLR(i) (0x080F + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_FALL(i) (0x0810 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_FALL_SET(i) (0x0811 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_EN_FALL_CLR(i) (0x0812 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_STATUS(i) (0x0813 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_LATCH(i) (0x0814 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_DEBUG(i) (0x0815 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_SCRATCH_REGISTER(i) (0x0816 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_SCRATCH_REGISTER_SET(i) (0x0817 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_SCRATCH_REGISTER_CLR(i) (0x0818 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_EXTENDED_SET_ACCESS(i) (0x082F + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_EN(i) (0x0830 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_EN_SET(i) (0x0831 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_EN_CLR(i) (0x0832 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_STATUS(i) (0x0833 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VCONTROL_LATCH(i) (0x0834 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VSTATUS(i) (0x0835 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VSTATUS_SET(i) (0x0836 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_UTMI_VSTATUS_CLR(i) (0x0837 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_USB_INT_LATCH_NOCLR(i) (0x0838 + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_EN(i) (0x083B + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_EN_SET(i) (0x083C + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_EN_CLR(i) (0x083D + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_STATUS(i) (0x083E + (0x100 * (i)))
+#define OMAP_USBTLL_ULPI_VENDOR_INT_LATCH(i) (0x083F + (0x100 * (i)))
+
+
+/*
+ * USB Host Module
+ */
+
+/* UHH */
+#define OMAP_USBHOST_UHH_REVISION 0x0000
+#define OMAP_USBHOST_UHH_SYSCONFIG 0x0010
+#define OMAP_USBHOST_UHH_SYSSTATUS 0x0014
+#define OMAP_USBHOST_UHH_HOSTCONFIG 0x0040
+#define OMAP_USBHOST_UHH_DEBUG_CSR 0x0044
+
+/* EHCI */
+#define OMAP_USBHOST_HCCAPBASE 0x0000
+#define OMAP_USBHOST_HCSPARAMS 0x0004
+#define OMAP_USBHOST_HCCPARAMS 0x0008
+#define OMAP_USBHOST_USBCMD 0x0010
+#define OMAP_USBHOST_USBSTS 0x0014
+#define OMAP_USBHOST_USBINTR 0x0018
+#define OMAP_USBHOST_FRINDEX 0x001C
+#define OMAP_USBHOST_CTRLDSSEGMENT 0x0020
+#define OMAP_USBHOST_PERIODICLISTBASE 0x0024
+#define OMAP_USBHOST_ASYNCLISTADDR 0x0028
+#define OMAP_USBHOST_CONFIGFLAG 0x0050
+#define OMAP_USBHOST_PORTSC(i) (0x0054 + (0x04 * (i)))
+#define OMAP_USBHOST_INSNREG00 0x0090
+#define OMAP_USBHOST_INSNREG01 0x0094
+#define OMAP_USBHOST_INSNREG02 0x0098
+#define OMAP_USBHOST_INSNREG03 0x009C
+#define OMAP_USBHOST_INSNREG04 0x00A0
+#define OMAP_USBHOST_INSNREG05_UTMI 0x00A4
+#define OMAP_USBHOST_INSNREG05_ULPI 0x00A4
+#define OMAP_USBHOST_INSNREG06 0x00A8
+#define OMAP_USBHOST_INSNREG07 0x00AC
+#define OMAP_USBHOST_INSNREG08 0x00B0
+
+#define OMAP_USBHOST_INSNREG04_DISABLE_UNSUSPEND (1 << 5)
+
+#define OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT 31
+#define OMAP_USBHOST_INSNREG05_ULPI_PORTSEL_SHIFT 24
+#define OMAP_USBHOST_INSNREG05_ULPI_OPSEL_SHIFT 22
+#define OMAP_USBHOST_INSNREG05_ULPI_REGADD_SHIFT 16
+#define OMAP_USBHOST_INSNREG05_ULPI_EXTREGADD_SHIFT 8
+#define OMAP_USBHOST_INSNREG05_ULPI_WRDATA_SHIFT 0
+
+
+
+
+
+/* TLL Register Set */
+#define TLL_SYSCONFIG_CACTIVITY (1UL << 8)
+#define TLL_SYSCONFIG_SIDLE_SMART_IDLE (2UL << 3)
+#define TLL_SYSCONFIG_SIDLE_NO_IDLE (1UL << 3)
+#define TLL_SYSCONFIG_SIDLE_FORCED_IDLE (0UL << 3)
+#define TLL_SYSCONFIG_ENAWAKEUP (1UL << 2)
+#define TLL_SYSCONFIG_SOFTRESET (1UL << 1)
+#define TLL_SYSCONFIG_AUTOIDLE (1UL << 0)
+
+#define TLL_SYSSTATUS_RESETDONE (1UL << 0)
+
+#define TLL_SHARED_CONF_USB_90D_DDR_EN (1UL << 6)
+#define TLL_SHARED_CONF_USB_180D_SDR_EN (1UL << 5)
+#define TLL_SHARED_CONF_USB_DIVRATIO_MASK (7UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_128 (7UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_64 (6UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_32 (5UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_16 (4UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_8 (3UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_4 (2UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_2 (1UL << 2)
+#define TLL_SHARED_CONF_USB_DIVRATIO_1 (0UL << 2)
+#define TLL_SHARED_CONF_FCLK_REQ (1UL << 1)
+#define TLL_SHARED_CONF_FCLK_IS_ON (1UL << 0)
+
+#define TLL_CHANNEL_CONF_DRVVBUS (1UL << 16)
+#define TLL_CHANNEL_CONF_CHRGVBUS (1UL << 15)
+#define TLL_CHANNEL_CONF_ULPINOBITSTUFF (1UL << 11)
+#define TLL_CHANNEL_CONF_ULPIAUTOIDLE (1UL << 10)
+#define TLL_CHANNEL_CONF_UTMIAUTOIDLE (1UL << 9)
+#define TLL_CHANNEL_CONF_ULPIDDRMODE (1UL << 8)
+#define TLL_CHANNEL_CONF_ULPIOUTCLKMODE (1UL << 7)
+#define TLL_CHANNEL_CONF_TLLFULLSPEED (1UL << 6)
+#define TLL_CHANNEL_CONF_TLLCONNECT (1UL << 5)
+#define TLL_CHANNEL_CONF_TLLATTACH (1UL << 4)
+#define TLL_CHANNEL_CONF_UTMIISADEV (1UL << 3)
+#define TLL_CHANNEL_CONF_CHANEN (1UL << 0)
+
+
+/* UHH Register Set */
+#define UHH_SYSCONFIG_MIDLEMODE_MASK (3UL << 12)
+#define UHH_SYSCONFIG_MIDLEMODE_SMARTSTANDBY (2UL << 12)
+#define UHH_SYSCONFIG_MIDLEMODE_NOSTANDBY (1UL << 12)
+#define UHH_SYSCONFIG_MIDLEMODE_FORCESTANDBY (0UL << 12)
+#define UHH_SYSCONFIG_CLOCKACTIVITY (1UL << 8)
+#define UHH_SYSCONFIG_SIDLEMODE_MASK (3UL << 3)
+#define UHH_SYSCONFIG_SIDLEMODE_SMARTIDLE (2UL << 3)
+#define UHH_SYSCONFIG_SIDLEMODE_NOIDLE (1UL << 3)
+#define UHH_SYSCONFIG_SIDLEMODE_FORCEIDLE (0UL << 3)
+#define UHH_SYSCONFIG_ENAWAKEUP (1UL << 2)
+#define UHH_SYSCONFIG_SOFTRESET (1UL << 1)
+#define UHH_SYSCONFIG_AUTOIDLE (1UL << 0)
+
+#define UHH_HOSTCONFIG_APP_START_CLK (1UL << 31)
+#define UHH_HOSTCONFIG_P3_CONNECT_STATUS (1UL << 10)
+#define UHH_HOSTCONFIG_P2_CONNECT_STATUS (1UL << 9)
+#define UHH_HOSTCONFIG_P1_CONNECT_STATUS (1UL << 8)
+#define UHH_HOSTCONFIG_ENA_INCR_ALIGN (1UL << 5)
+#define UHH_HOSTCONFIG_ENA_INCR16 (1UL << 4)
+#define UHH_HOSTCONFIG_ENA_INCR8 (1UL << 3)
+#define UHH_HOSTCONFIG_ENA_INCR4 (1UL << 2)
+#define UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN (1UL << 1)
+#define UHH_HOSTCONFIG_P1_ULPI_BYPASS (1UL << 0)
+
+/* The following are on rev2 (OMAP44xx) of the EHCI only */
+#define UHH_SYSCONFIG_IDLEMODE_MASK (3UL << 2)
+#define UHH_SYSCONFIG_IDLEMODE_NOIDLE (1UL << 2)
+#define UHH_SYSCONFIG_STANDBYMODE_MASK (3UL << 4)
+#define UHH_SYSCONFIG_STANDBYMODE_NOSTDBY (1UL << 4)
+
+#define UHH_HOSTCONFIG_P1_MODE_MASK (3UL << 16)
+#define UHH_HOSTCONFIG_P1_MODE_ULPI_PHY (0UL << 16)
+#define UHH_HOSTCONFIG_P1_MODE_UTMI_PHY (1UL << 16)
+#define UHH_HOSTCONFIG_P1_MODE_HSIC (3UL << 16)
+#define UHH_HOSTCONFIG_P2_MODE_MASK (3UL << 18)
+#define UHH_HOSTCONFIG_P2_MODE_ULPI_PHY (0UL << 18)
+#define UHH_HOSTCONFIG_P2_MODE_UTMI_PHY (1UL << 18)
+#define UHH_HOSTCONFIG_P2_MODE_HSIC (3UL << 18)
+
+#define ULPI_FUNC_CTRL_RESET (1 << 5)
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Macros for Set and Clear
+ * See ULPI 1.1 specification to find the registers with Set and Clear offsets
+ */
+#define ULPI_SET(a) (a + 1)
+#define ULPI_CLR(a) (a + 2)
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Register Map
+ */
+#define ULPI_VENDOR_ID_LOW 0x00
+#define ULPI_VENDOR_ID_HIGH 0x01
+#define ULPI_PRODUCT_ID_LOW 0x02
+#define ULPI_PRODUCT_ID_HIGH 0x03
+#define ULPI_FUNC_CTRL 0x04
+#define ULPI_IFC_CTRL 0x07
+#define ULPI_OTG_CTRL 0x0a
+#define ULPI_USB_INT_EN_RISE 0x0d
+#define ULPI_USB_INT_EN_FALL 0x10
+#define ULPI_USB_INT_STS 0x13
+#define ULPI_USB_INT_LATCH 0x14
+#define ULPI_DEBUG 0x15
+#define ULPI_SCRATCH 0x16
+
+/*
+ * Values of UHH_REVISION - Note: these are not given in the TRM but taken
+ * from the linux OMAP EHCI driver (thanks guys). It has been verified on
+ * a Panda and Beagle board.
+ */
+#define OMAP_EHCI_REV1 0x00000010 /* OMAP3 */
+#define OMAP_EHCI_REV2 0x50700100 /* OMAP4 */
+
+#define EHCI_VENDORID_OMAP3 0x42fa05
+#define OMAP_EHCI_HC_DEVSTR "TI OMAP USB 2.0 controller"
+
+#define EHCI_HCD_OMAP_MODE_UNKNOWN 0
+#define EHCI_HCD_OMAP_MODE_PHY 1
+#define EHCI_HCD_OMAP_MODE_TLL 2
+#define EHCI_HCD_OMAP_MODE_HSIC 3
--- /dev/null
+/* $OpenBSD: omgpio.c,v 1.6 2016/01/31 00:14:50 jsg Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/evcount.h>
+#include <sys/gpio.h>
+
+#include <arm/cpufunc.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/gpio/gpiovar.h>
+
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/prcmvar.h>
+#include <armv7/omap/sitara_cm.h>
+#include <armv7/omap/omgpiovar.h>
+
+#include "gpio.h"
+
+/* OMAP3 registers */
+#define GPIO3_REVISION 0x00
+#define GPIO3_SYSCONFIG 0x10
+#define GPIO3_SYSSTATUS 0x14
+#define GPIO3_IRQSTATUS1 0x18
+#define GPIO3_IRQENABLE1 0x1C
+#define GPIO3_WAKEUPENABLE 0x20
+#define GPIO3_IRQSTATUS2 0x28
+#define GPIO3_IRQENABLE2 0x2C
+#define GPIO3_CTRL 0x30
+#define GPIO3_OE 0x34
+#define GPIO3_DATAIN 0x38
+#define GPIO3_DATAOUT 0x3C
+#define GPIO3_LEVELDETECT0 0x40
+#define GPIO3_LEVELDETECT1 0x44
+#define GPIO3_RISINGDETECT 0x48
+#define GPIO3_FALLINGDETECT 0x4C
+#define GPIO3_DEBOUNCENABLE 0x50
+#define GPIO3_DEBOUNCINGTIME 0x54
+#define GPIO3_CLEARIRQENABLE1 0x60
+#define GPIO3_SETIRQENABLE1 0x64
+#define GPIO3_CLEARIRQENABLE2 0x70
+#define GPIO3_SETIRQENABLE2 0x74
+#define GPIO3_CLEARWKUENA 0x80
+#define GPIO3_SETWKUENA 0x84
+#define GPIO3_CLEARDATAOUT 0x90
+#define GPIO3_SETDATAOUT 0x94
+
+/* OMAP4 registers */
+#define GPIO4_REVISION 0x00
+#define GPIO4_SYSCONFIG 0x10
+#define GPIO4_IRQSTATUS_RAW_0 0x24
+#define GPIO4_IRQSTATUS_RAW_1 0x28
+#define GPIO4_IRQSTATUS_0 0x2C
+#define GPIO4_IRQSTATUS_1 0x30
+#define GPIO4_IRQSTATUS_SET_0 0x34
+#define GPIO4_IRQSTATUS_SET_1 0x38
+#define GPIO4_IRQSTATUS_CLR_0 0x3C
+#define GPIO4_IRQSTATUS_CLR_1 0x40
+#define GPIO4_IRQWAKEN_0 0x44
+#define GPIO4_IRQWAKEN_1 0x48
+#define GPIO4_SYSSTATUS 0x114
+#define GPIO4_WAKEUPENABLE 0x120
+#define GPIO4_CTRL 0x130
+#define GPIO4_OE 0x134
+#define GPIO4_DATAIN 0x138
+#define GPIO4_DATAOUT 0x13C
+#define GPIO4_LEVELDETECT0 0x140
+#define GPIO4_LEVELDETECT1 0x144
+#define GPIO4_RISINGDETECT 0x148
+#define GPIO4_FALLINGDETECT 0x14C
+#define GPIO4_DEBOUNCENABLE 0x150
+#define GPIO4_DEBOUNCINGTIME 0x154
+#define GPIO4_CLEARWKUPENA 0x180
+#define GPIO4_SETWKUENA 0x184
+#define GPIO4_CLEARDATAOUT 0x190
+#define GPIO4_SETDATAOUT 0x194
+
+/* AM335X registers */
+#define GPIO_AM335X_REVISION 0x00
+#define GPIO_AM335X_SYSCONFIG 0x10
+#define GPIO_AM335X_IRQSTATUS_RAW_0 0x24
+#define GPIO_AM335X_IRQSTATUS_RAW_1 0x28
+#define GPIO_AM335X_IRQSTATUS_0 0x2C
+#define GPIO_AM335X_IRQSTATUS_1 0x30
+#define GPIO_AM335X_IRQSTATUS_SET_0 0x34
+#define GPIO_AM335X_IRQSTATUS_SET_1 0x38
+#define GPIO_AM335X_IRQSTATUS_CLR_0 0x3c
+#define GPIO_AM335X_IRQSTATUS_CLR_1 0x40
+#define GPIO_AM335X_IRQWAKEN_0 0x44
+#define GPIO_AM335X_IRQWAKEN_1 0x48
+#define GPIO_AM335X_SYSSTATUS 0x114
+#define GPIO_AM335X_CTRL 0x130
+#define GPIO_AM335X_OE 0x134
+#define GPIO_AM335X_DATAIN 0x138
+#define GPIO_AM335X_DATAOUT 0x13C
+#define GPIO_AM335X_LEVELDETECT0 0x140
+#define GPIO_AM335X_LEVELDETECT1 0x144
+#define GPIO_AM335X_RISINGDETECT 0x148
+#define GPIO_AM335X_FALLINGDETECT 0x14C
+#define GPIO_AM335X_DEBOUNCENABLE 0x150
+#define GPIO_AM335X_DEBOUNCINGTIME 0x154
+#define GPIO_AM335X_CLEARDATAOUT 0x190
+#define GPIO_AM335X_SETDATAOUT 0x194
+
+#define GPIO_NUM_PINS 32
+
+struct intrhand {
+ int (*ih_func)(void *); /* handler */
+ void *ih_arg; /* arg for handler */
+ int ih_ipl; /* IPL_* */
+ int ih_irq; /* IRQ number */
+ int ih_gpio; /* gpio pin */
+ struct evcount ih_count;
+ char *ih_name;
+};
+
+struct omgpio_regs {
+ u_int32_t revision;
+ u_int32_t sysconfig;
+ u_int32_t irqstatus_raw0; /* omap4/am335x only */
+ u_int32_t irqstatus_raw1; /* omap4/am335x only */
+ u_int32_t irqstatus0;
+ u_int32_t irqstatus1;
+ u_int32_t irqstatus_set0;
+ u_int32_t irqstatus_set1;
+ u_int32_t irqstatus_clear0;
+ u_int32_t irqstatus_clear1;
+ u_int32_t irqwaken0;
+ u_int32_t irqwaken1;
+ u_int32_t sysstatus;
+ u_int32_t wakeupenable; /* omap3/omap4 only */
+ u_int32_t ctrl;
+ u_int32_t oe;
+ u_int32_t datain;
+ u_int32_t dataout;
+ u_int32_t leveldetect0;
+ u_int32_t leveldetect1;
+ u_int32_t risingdetect;
+ u_int32_t fallingdetect;
+ u_int32_t debounceenable;
+ u_int32_t debouncingtime;
+ u_int32_t clearwkupena; /* omap3/omap4 only */
+ u_int32_t setwkupena; /* omap3/omap4 only */
+ u_int32_t cleardataout;
+ u_int32_t setdataout;
+};
+
+struct omgpio_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ void *sc_ih_h;
+ void *sc_ih_l;
+ int sc_max_il;
+ int sc_min_il;
+ int sc_irq;
+ struct intrhand *sc_handlers[GPIO_NUM_PINS];
+ int sc_omap_ver;
+ struct gpio_chipset_tag sc_gpio_gc;
+ gpio_pin_t sc_gpio_pins[GPIO_NUM_PINS];
+ struct omgpio_regs sc_regs;
+};
+
+#define GPIO_PIN_TO_INST(x) ((x) >> 5)
+#define GPIO_PIN_TO_OFFSET(x) ((x) & 0x1f)
+#define DEVNAME(sc) ((sc)->sc_dev.dv_xname)
+#define READ4(sc, reg) omgpio_read4(sc, reg)
+#define WRITE4(sc, reg, val) omgpio_write4(sc, reg, val)
+
+u_int32_t omgpio_read4(struct omgpio_softc *, u_int32_t);
+void omgpio_write4(struct omgpio_softc *, u_int32_t, u_int32_t);
+int omgpio_match(struct device *, void *, void *);
+void omgpio_attach(struct device *, struct device *, void *);
+void omgpio_recalc_interrupts(struct omgpio_softc *);
+int omgpio_irq(void *);
+int omgpio_irq_dummy(void *);
+int omgpio_pin_dir_read(struct omgpio_softc *, unsigned int);
+void omgpio_pin_dir_write(struct omgpio_softc *, unsigned int, unsigned int);
+
+struct cfattach omgpio_ca = {
+ sizeof (struct omgpio_softc), omgpio_match, omgpio_attach
+};
+
+struct cfdriver omgpio_cd = {
+ NULL, "omgpio", DV_DULL
+};
+
+u_int32_t
+omgpio_read4(struct omgpio_softc *sc, u_int32_t reg)
+{
+ if(reg == -1)
+ panic("%s: Invalid register address", DEVNAME(sc));
+
+ return bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg));
+}
+
+void
+omgpio_write4(struct omgpio_softc *sc, u_int32_t reg, u_int32_t val)
+{
+ if(reg == -1)
+ panic("%s: Invalid register address", DEVNAME(sc));
+
+ bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val));
+}
+
+int
+omgpio_match(struct device *parent, void *v, void *aux)
+{
+ switch (board_id) {
+ case BOARD_ID_OMAP3_BEAGLE:
+ case BOARD_ID_OMAP3_OVERO:
+ case BOARD_ID_AM335X_BEAGLEBONE:
+ case BOARD_ID_OMAP4_PANDA:
+ break; /* continue trying */
+ default:
+ return 0; /* unknown */
+ }
+ return (1);
+}
+
+void
+omgpio_attach(struct device *parent, struct device *self, void *args)
+{
+ struct armv7_attach_args *aa = args;
+ struct omgpio_softc *sc = (struct omgpio_softc *) self;
+ struct gpiobus_attach_args gba;
+ u_int32_t rev;
+ int i;
+
+ prcm_enablemodule(PRCM_GPIO0 + aa->aa_dev->unit);
+
+ sc->sc_iot = aa->aa_iot;
+ if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
+ panic("%s: bus_space_map failed!", DEVNAME(sc));
+
+ switch (board_id) {
+ case BOARD_ID_OMAP3_BEAGLE:
+ case BOARD_ID_OMAP3_OVERO:
+ sc->sc_regs.revision = GPIO3_REVISION;
+ sc->sc_regs.sysconfig = GPIO3_SYSCONFIG;
+ sc->sc_regs.irqstatus_raw0 = -1;
+ sc->sc_regs.irqstatus_raw1 = -1;
+ sc->sc_regs.irqstatus0 = GPIO3_IRQSTATUS1;
+ sc->sc_regs.irqstatus1 = GPIO3_IRQSTATUS2;
+ sc->sc_regs.irqstatus_set0 = GPIO3_SETIRQENABLE1;
+ sc->sc_regs.irqstatus_set1 = GPIO3_SETIRQENABLE2;
+ sc->sc_regs.irqstatus_clear0 = GPIO3_CLEARIRQENABLE1;
+ sc->sc_regs.irqstatus_clear1 = GPIO3_CLEARIRQENABLE2;
+ sc->sc_regs.irqwaken0 = -1;
+ sc->sc_regs.irqwaken1 = -1;
+ sc->sc_regs.sysstatus = GPIO3_SYSSTATUS;
+ sc->sc_regs.wakeupenable = GPIO3_WAKEUPENABLE;
+ sc->sc_regs.ctrl = GPIO3_CTRL;
+ sc->sc_regs.oe = GPIO3_OE;
+ sc->sc_regs.datain = GPIO3_DATAIN;
+ sc->sc_regs.dataout = GPIO3_DATAOUT;
+ sc->sc_regs.leveldetect0 = GPIO3_LEVELDETECT0;
+ sc->sc_regs.leveldetect1 = GPIO3_LEVELDETECT1;
+ sc->sc_regs.risingdetect = GPIO3_RISINGDETECT;
+ sc->sc_regs.fallingdetect = GPIO3_FALLINGDETECT;
+ sc->sc_regs.debounceenable = GPIO3_DEBOUNCENABLE;
+ sc->sc_regs.debouncingtime = GPIO3_DEBOUNCINGTIME;
+ sc->sc_regs.clearwkupena = GPIO3_CLEARWKUENA;
+ sc->sc_regs.setwkupena = GPIO3_SETWKUENA;
+ sc->sc_regs.cleardataout = GPIO3_CLEARDATAOUT;
+ sc->sc_regs.setdataout = GPIO3_SETDATAOUT;
+ break;
+ case BOARD_ID_OMAP4_PANDA:
+ sc->sc_regs.revision = GPIO4_REVISION;
+ sc->sc_regs.sysconfig = GPIO4_SYSCONFIG;
+ sc->sc_regs.irqstatus_raw0 = GPIO4_IRQSTATUS_RAW_0;
+ sc->sc_regs.irqstatus_raw1 = GPIO4_IRQSTATUS_RAW_1;
+ sc->sc_regs.irqstatus0 = GPIO4_IRQSTATUS_0;
+ sc->sc_regs.irqstatus1 = GPIO4_IRQSTATUS_1;
+ sc->sc_regs.irqstatus_set0 = GPIO4_IRQSTATUS_SET_0;
+ sc->sc_regs.irqstatus_set1 = GPIO4_IRQSTATUS_SET_1;
+ sc->sc_regs.irqstatus_clear0 = GPIO4_IRQSTATUS_CLR_0;
+ sc->sc_regs.irqstatus_clear1 = GPIO4_IRQSTATUS_CLR_1;
+ sc->sc_regs.irqwaken0 = GPIO4_IRQWAKEN_0;
+ sc->sc_regs.irqwaken1 = GPIO4_IRQWAKEN_1;
+ sc->sc_regs.sysstatus = GPIO4_SYSSTATUS;
+ sc->sc_regs.wakeupenable = GPIO4_WAKEUPENABLE;
+ sc->sc_regs.ctrl = GPIO4_CTRL;
+ sc->sc_regs.oe = GPIO4_OE;
+ sc->sc_regs.datain = GPIO4_DATAIN;
+ sc->sc_regs.dataout = GPIO4_DATAOUT;
+ sc->sc_regs.leveldetect0 = GPIO4_LEVELDETECT0;
+ sc->sc_regs.leveldetect1 = GPIO4_LEVELDETECT1;
+ sc->sc_regs.risingdetect = GPIO4_RISINGDETECT;
+ sc->sc_regs.fallingdetect = GPIO4_FALLINGDETECT;
+ sc->sc_regs.debounceenable = GPIO4_DEBOUNCENABLE;
+ sc->sc_regs.debouncingtime = GPIO4_DEBOUNCINGTIME;
+ sc->sc_regs.clearwkupena = GPIO4_CLEARWKUPENA;
+ sc->sc_regs.setwkupena = GPIO4_SETWKUENA;
+ sc->sc_regs.cleardataout = GPIO4_CLEARDATAOUT;
+ sc->sc_regs.setdataout = GPIO4_SETDATAOUT;
+ break;
+ case BOARD_ID_AM335X_BEAGLEBONE:
+ sc->sc_regs.revision = GPIO_AM335X_REVISION;
+ sc->sc_regs.sysconfig = GPIO_AM335X_SYSCONFIG;
+ sc->sc_regs.irqstatus_raw0 = GPIO_AM335X_IRQSTATUS_RAW_0;
+ sc->sc_regs.irqstatus_raw1 = GPIO_AM335X_IRQSTATUS_RAW_1;
+ sc->sc_regs.irqstatus0 = GPIO_AM335X_IRQSTATUS_0;
+ sc->sc_regs.irqstatus1 = GPIO_AM335X_IRQSTATUS_1;
+ sc->sc_regs.irqstatus_set0 = GPIO_AM335X_IRQSTATUS_SET_0;
+ sc->sc_regs.irqstatus_set1 = GPIO_AM335X_IRQSTATUS_SET_1;
+ sc->sc_regs.irqstatus_clear0 = GPIO_AM335X_IRQSTATUS_CLR_0;
+ sc->sc_regs.irqstatus_clear1 = GPIO_AM335X_IRQSTATUS_CLR_1;
+ sc->sc_regs.irqwaken0 = GPIO_AM335X_IRQWAKEN_0;
+ sc->sc_regs.irqwaken1 = GPIO_AM335X_IRQWAKEN_1;
+ sc->sc_regs.sysstatus = GPIO_AM335X_SYSSTATUS;
+ sc->sc_regs.wakeupenable = -1;
+ sc->sc_regs.ctrl = GPIO_AM335X_CTRL;
+ sc->sc_regs.oe = GPIO_AM335X_OE;
+ sc->sc_regs.datain = GPIO_AM335X_DATAIN;
+ sc->sc_regs.dataout = GPIO_AM335X_DATAOUT;
+ sc->sc_regs.leveldetect0 = GPIO_AM335X_LEVELDETECT0;
+ sc->sc_regs.leveldetect1 = GPIO_AM335X_LEVELDETECT1;
+ sc->sc_regs.risingdetect = GPIO_AM335X_RISINGDETECT;
+ sc->sc_regs.fallingdetect = GPIO_AM335X_FALLINGDETECT;
+ sc->sc_regs.debounceenable = GPIO_AM335X_DEBOUNCENABLE;
+ sc->sc_regs.debouncingtime = GPIO_AM335X_DEBOUNCINGTIME;
+ sc->sc_regs.clearwkupena = -1;
+ sc->sc_regs.setwkupena = -1;
+ sc->sc_regs.cleardataout = GPIO_AM335X_CLEARDATAOUT;
+ sc->sc_regs.setdataout = GPIO_AM335X_SETDATAOUT;
+ break;
+ }
+
+ rev = READ4(sc, sc->sc_regs.revision);
+
+ printf(": rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
+
+ sc->sc_irq = aa->aa_dev->irq[0];
+
+ WRITE4(sc, sc->sc_regs.irqstatus_clear0, ~0);
+ WRITE4(sc, sc->sc_regs.irqstatus_clear1, ~0);
+
+ /* XXX - SYSCONFIG */
+ /* XXX - CTRL */
+ /* XXX - DEBOUNCE */
+
+ for (i = 0; i < GPIO_NUM_PINS; i++) {
+ sc->sc_gpio_pins[i].pin_num = i;
+ sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
+ GPIO_PIN_OUTPUT | GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
+ sc->sc_gpio_pins[i].pin_state = omgpio_pin_read(sc, i) ?
+ GPIO_PIN_HIGH : GPIO_PIN_LOW;
+ sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_SET;
+ }
+
+ sc->sc_gpio_gc.gp_cookie = sc;
+ sc->sc_gpio_gc.gp_pin_read = omgpio_pin_read;
+ sc->sc_gpio_gc.gp_pin_write = omgpio_pin_write;
+ sc->sc_gpio_gc.gp_pin_ctl = omgpio_pin_ctl;
+
+ gba.gba_name = "gpio";
+ gba.gba_gc = &sc->sc_gpio_gc;
+ gba.gba_pins = sc->sc_gpio_pins;
+ gba.gba_npins = GPIO_NUM_PINS;
+
+#if NGPIO > 0
+ config_found(&sc->sc_dev, &gba, gpiobus_print);
+#endif
+}
+
+/* XXX - This assumes MCU INTERRUPTS are IRQ1, and DSP are IRQ2 */
+
+#if 0
+/* XXX - FIND THESE REGISTERS !!! */
+unsigned int
+omgpio_get_function(unsigned int gpio, unsigned int fn)
+{
+ return 0;
+}
+
+void
+omgpio_set_function(unsigned int gpio, unsigned int fn)
+{
+}
+#endif
+
+unsigned int
+omgpio_get_bit(unsigned int gpio)
+{
+ struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
+
+ return omgpio_pin_read(sc, GPIO_PIN_TO_OFFSET(gpio));
+}
+
+void
+omgpio_set_bit(unsigned int gpio)
+{
+ struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
+
+ omgpio_pin_write(sc, GPIO_PIN_TO_OFFSET(gpio), GPIO_PIN_HIGH);
+}
+
+void
+omgpio_clear_bit(unsigned int gpio)
+{
+ struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
+
+ omgpio_pin_write(sc, GPIO_PIN_TO_OFFSET(gpio), GPIO_PIN_LOW);
+}
+
+void
+omgpio_set_dir(unsigned int gpio, unsigned int dir)
+{
+ struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
+
+ omgpio_pin_dir_write(sc, GPIO_PIN_TO_OFFSET(gpio), dir);
+}
+
+int
+omgpio_pin_read(void *arg, int pin)
+{
+ struct omgpio_softc *sc = arg;
+ u_int32_t reg;
+
+ if(omgpio_pin_dir_read(sc, pin) == OMGPIO_DIR_IN)
+ reg = READ4(sc, sc->sc_regs.datain);
+ else
+ reg = READ4(sc, sc->sc_regs.dataout);
+ return (reg >> GPIO_PIN_TO_OFFSET(pin)) & 0x1;
+}
+
+void
+omgpio_pin_write(void *arg, int pin, int value)
+{
+ struct omgpio_softc *sc = arg;
+
+ if (value)
+ WRITE4(sc, sc->sc_regs.setdataout,
+ 1 << GPIO_PIN_TO_OFFSET(pin));
+ else
+ WRITE4(sc, sc->sc_regs.cleardataout,
+ 1 << GPIO_PIN_TO_OFFSET(pin));
+}
+
+void
+omgpio_pin_ctl(void *arg, int pin, int flags)
+{
+ struct omgpio_softc *sc = arg;
+
+ if (flags & GPIO_PIN_INPUT)
+ omgpio_pin_dir_write(sc, pin, OMGPIO_DIR_IN);
+ else if (flags & GPIO_PIN_OUTPUT)
+ omgpio_pin_dir_write(sc, pin, OMGPIO_DIR_OUT);
+
+ if (board_id == BOARD_ID_AM335X_BEAGLEBONE)
+ sitara_cm_padconf_set_gpioflags(
+ sc->sc_dev.dv_unit * GPIO_NUM_PINS + pin, flags);
+}
+
+void
+omgpio_pin_dir_write(struct omgpio_softc *sc, unsigned int gpio,
+ unsigned int dir)
+{
+ int s;
+ u_int32_t reg;
+
+ s = splhigh();
+
+ reg = READ4(sc, sc->sc_regs.oe);
+ if (dir == OMGPIO_DIR_IN)
+ reg |= 1 << GPIO_PIN_TO_OFFSET(gpio);
+ else
+ reg &= ~(1 << GPIO_PIN_TO_OFFSET(gpio));
+ WRITE4(sc, sc->sc_regs.oe, reg);
+
+ splx(s);
+}
+
+int
+omgpio_pin_dir_read(struct omgpio_softc *sc, unsigned int gpio)
+{
+ u_int32_t reg;
+ reg = READ4(sc, sc->sc_regs.oe);
+ if (reg & (1 << GPIO_PIN_TO_OFFSET(gpio)))
+ return OMGPIO_DIR_IN;
+ else
+ return OMGPIO_DIR_OUT;
+}
+
+#if 0
+void
+omgpio_clear_intr(struct omgpio_softc *sc, unsigned int gpio)
+{
+ struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
+
+ WRITE4(sc, sc->sc_regs.irqstatus0, 1 << GPIO_PIN_TO_OFFSET(gpio));
+}
+
+void
+omgpio_intr_mask(struct omgpio_softc *sc, unsigned int gpio)
+{
+ struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
+
+ WRITE4(sc, sc->sc_regs.irqstatus_clear0, 1 << GPIO_PIN_TO_OFFSET(gpio));
+}
+
+void
+omgpio_intr_unmask(struct omgpio_softc *sc, unsigned int gpio)
+{
+ struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
+
+ WRITE4(sc, sc->sc_regs.irqstatus_set0, 1 << GPIO_PIN_TO_OFFSET(gpio));
+}
+
+void
+omgpio_intr_level(struct omgpio_softc *sc, unsigned int gpio, unsigned int level)
+{
+ u_int32_t fe, re, l0, l1, bit;
+ struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
+ int s;
+
+ s = splhigh();
+
+ fe = READ4(sc, sc->sc_regs.fallingdetect);
+ re = READ4(sc, sc->sc_regs.risingdetect);
+ l0 = READ4(sc, sc->sc_regs.leveldetect0);
+ l1 = READ4(sc, sc->sc_regs.leveldetect1);
+
+ bit = 1 << GPIO_PIN_TO_OFFSET(gpio);
+
+ switch (level) {
+ case IST_NONE:
+ fe &= ~bit;
+ re &= ~bit;
+ l0 &= ~bit;
+ l1 &= ~bit;
+ break;
+ case IST_EDGE_FALLING:
+ fe |= bit;
+ re &= ~bit;
+ l0 &= ~bit;
+ l1 &= ~bit;
+ break;
+ case IST_EDGE_RISING:
+ fe &= ~bit;
+ re |= bit;
+ l0 &= ~bit;
+ l1 &= ~bit;
+ break;
+ case IST_PULSE: /* XXX */
+ /* FALLTHRU */
+ case IST_EDGE_BOTH:
+ fe |= bit;
+ re |= bit;
+ l0 &= ~bit;
+ l1 &= ~bit;
+ break;
+ case IST_LEVEL_LOW:
+ fe &= ~bit;
+ re &= ~bit;
+ l0 |= bit;
+ l1 &= ~bit;
+ break;
+ case IST_LEVEL_HIGH:
+ fe &= ~bit;
+ re &= ~bit;
+ l0 &= ~bit;
+ l1 |= bit;
+ break;
+ default:
+ panic("omgpio_intr_level: bad level: %d", level);
+ break;
+ }
+
+ WRITE4(sc, sc->sc_regs.fallingdetect, fe);
+ WRITE4(sc, sc->sc_regs.risingdetect, re);
+ WRITE4(sc, sc->sc_regs.leveldetect0, l0);
+ WRITE4(sc, sc->sc_regs.leveldetect1, l1);
+
+ splx(s);
+}
+
+void *
+omgpio_intr_establish(struct omgpio_softc *sc, unsigned int gpio, int level, int spl,
+ int (*func)(void *), void *arg, char *name)
+{
+ int psw;
+ struct intrhand *ih;
+ struct omgpio_softc *sc;
+
+ /*
+ * XXX - is gpio here the pin or the interrupt number
+ * which is 96 + gpio pin?
+ */
+
+ if (GPIO_PIN_TO_INST(gpio) > omgpio_cd.cd_ndevs)
+ panic("omgpio_intr_establish: bogus irqnumber %d: %s",
+ gpio, name);
+
+ sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(gpio)];
+
+ if (sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)] != NULL)
+ panic("omgpio_intr_establish: gpio pin busy %d old %s new %s",
+ gpio, sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)]->ih_name,
+ name);
+
+ psw = disable_interrupts(PSR_I);
+
+ /* no point in sleeping unless someone can free memory. */
+ ih = (struct intrhand *)malloc( sizeof *ih, M_DEVBUF,
+ cold ? M_NOWAIT : M_WAITOK);
+ if (ih == NULL)
+ panic("intr_establish: can't malloc handler info");
+ ih->ih_func = func;
+ ih->ih_arg = arg;
+ ih->ih_ipl = level;
+ ih->ih_gpio = gpio;
+ ih->ih_irq = gpio + 512;
+ ih->ih_name = name;
+
+ sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)] = ih;
+
+ evcount_attach(&ih->ih_count, name, &ih->ih_irq);
+
+ omgpio_intr_level(gpio, level);
+ omgpio_intr_unmask(gpio);
+
+ omgpio_recalc_interrupts(sc);
+
+ restore_interrupts(psw);
+
+ return (ih);
+}
+
+void
+omgpio_intr_disestablish(struct omgpio_softc *sc, void *cookie)
+{
+ int psw;
+ struct intrhand *ih = cookie;
+ struct omgpio_softc *sc = omgpio_cd.cd_devs[GPIO_PIN_TO_INST(ih->ih_gpio)];
+ int gpio = ih->ih_gpio;
+ psw = disable_interrupts(PSR_I);
+
+ ih = sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)];
+ sc->sc_handlers[GPIO_PIN_TO_OFFSET(gpio)] = NULL;
+
+ evcount_detach(&ih->ih_count);
+
+ free(ih, M_DEVBUF, 0);
+
+ omgpio_intr_level(gpio, IST_NONE);
+ omgpio_intr_mask(gpio);
+ omgpio_clear_intr(gpio); /* Just in case */
+
+ omgpio_recalc_interrupts(sc);
+
+ restore_interrupts(psw);
+}
+
+int
+omgpio_irq(void *v)
+{
+ struct omgpio_softc *sc = v;
+ u_int32_t pending;
+ struct intrhand *ih;
+ int bit;
+
+ pending = READ4(sc, omgpio.irqstatus0);
+
+ while (pending != 0) {
+ bit = ffs(pending) - 1;
+ ih = sc->sc_handlers[bit];
+
+ if (ih != NULL) {
+ if (ih->ih_func(ih->ih_arg))
+ ih->ih_count.ec_count++;
+ omgpio_clear_intr(ih->ih_gpio);
+ } else {
+ panic("omgpio: irq fired no handler, gpio %x %x %x",
+ sc->sc_dev.dv_unit * 32 + bit, pending,
+ READ4(sc, omgpio.irqstatus0)
+
+ );
+ }
+ pending &= ~(1 << bit);
+ }
+ return 1;
+}
+
+int
+omgpio_irq_dummy(void *v)
+{
+ return 0;
+}
+
+void
+omgpio_recalc_interrupts(struct omgpio_softc *sc)
+{
+ struct intrhand *ih;
+ int max = IPL_NONE;
+ int min = IPL_HIGH;
+ int i;
+
+ for (i = 0; i < GPIO_NUM_PINS; i++) {
+ ih = sc->sc_handlers[i];
+ if (ih != NULL) {
+ if (ih->ih_ipl > max)
+ max = ih->ih_ipl;
+
+ if (ih->ih_ipl < min)
+ min = ih->ih_ipl;
+ }
+ }
+ if (max == IPL_NONE)
+ min = IPL_NONE;
+
+#if 0
+ if ((max == IPL_NONE || max != sc->sc_max_il) && sc->sc_ih_h != NULL)
+ arm_intr_disestablish(sc->sc_ih_h);
+
+ if (max != IPL_NONE && max != sc->sc_max_il) {
+ sc->sc_ih_h = arm_intr_establish(sc->sc_irq, max, omgpio_irq,
+ sc, NULL);
+ }
+#else
+ if (sc->sc_ih_h != NULL)
+ arm_intr_disestablish(sc->sc_ih_h);
+
+ if (max != IPL_NONE) {
+ sc->sc_ih_h = arm_intr_establish(sc->sc_irq, max, omgpio_irq,
+ sc, NULL);
+ }
+#endif
+
+ sc->sc_max_il = max;
+
+ if (sc->sc_ih_l != NULL)
+ arm_intr_disestablish(sc->sc_ih_l);
+
+ if (max != min) {
+ sc->sc_ih_h = arm_intr_establish(sc->sc_irq, min,
+ omgpio_irq_dummy, sc, NULL);
+ }
+ sc->sc_min_il = min;
+}
+#endif
--- /dev/null
+/* $OpenBSD: omgpiovar.h,v 1.2 2013/11/20 13:32:40 rapha Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef OMGPIOVAR_H
+#define OMGPIOVAR_H
+
+#define OMGPIO_DIR_IN 0
+#define OMGPIO_DIR_OUT 1
+
+unsigned int omgpio_get_function(unsigned int gpio, unsigned int fn);
+void omgpio_set_function(unsigned int gpio, unsigned int fn);
+unsigned int omgpio_get_bit(unsigned int gpio);
+void omgpio_set_bit(unsigned int gpio);
+void omgpio_clear_bit(unsigned int gpio);
+void omgpio_set_dir(unsigned int gpio, unsigned int dir);
+
+int omgpio_pin_read(void *arg, int pin);
+void omgpio_pin_write(void *arg, int pin, int value);
+void omgpio_pin_ctl(void *arg, int pin, int flags);
+
+/* interrupts */
+void omgpio_clear_intr(unsigned int gpio);
+void omgpio_intr_mask(unsigned int gpio);
+void omgpio_intr_unmask(unsigned int gpio);
+void omgpio_intr_level(unsigned int gpio, unsigned int level);
+void *omgpio_intr_establish(unsigned int gpio, int level, int spl,
+ int (*func)(void *), void *arg, char *name);
+void omgpio_intr_disestablish(void *cookie);
+
+#endif /* OMGPIOVAR_H */
--- /dev/null
+/* $OpenBSD: ommmc.c,v 1.18 2016/05/02 07:38:34 jsg Exp $ */
+
+/*
+ * Copyright (c) 2009 Dale Rahn <drahn@openbsd.org>
+ * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* Omap SD/MMC support derived from /sys/dev/sdmmc/sdhc.c */
+
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <machine/bus.h>
+
+#include <dev/sdmmc/sdmmcchip.h>
+#include <dev/sdmmc/sdmmcvar.h>
+
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/prcmvar.h>
+
+/*
+ * NOTE: on OMAP4430/AM335x these registers skew by 0x100
+ * this is handled by mapping at base address + 0x100
+ */
+/* registers */
+#define MMCHS_SYSCONFIG 0x010
+#define MMCHS_SYSSTATUS 0x014
+#define MMCHS_CSRE 0x024
+#define MMCHS_SYSTEST 0x028
+#define MMCHS_SYSTEST_SDCD (1 << 15)
+#define MMCHS_CON 0x02C
+#define MMCHS_CON_INIT (1<<1)
+#define MMCHS_CON_DW8 (1<<5)
+#define MMCHS_CON_OD (1<<0)
+#define MMCHS_PWCNT 0x030
+#define MMCHS_BLK 0x104
+#define MMCHS_BLK_NBLK_MAX 0xffff
+#define MMCHS_BLK_NBLK_SHIFT 16
+#define MMCHS_BLK_NBLK_MASK (MMCHS_BLK_NBLK_MAX<<MMCHS_BLK_NBLK_SHIFT)
+#define MMCHS_BLK_BLEN_MAX 0x400
+#define MMCHS_BLK_BLEN_SHIFT 0
+#define MMCHS_BLK_BLEN_MASK (MMCHS_BLK_BLEN_MAX<<MMCHS_BLK_BLEN_SHIFT)
+#define MMCHS_ARG 0x108
+#define MMCHS_CMD 0x10C
+#define MMCHS_CMD_INDX_SHIFT 24
+#define MMCHS_CMD_INDX_SHIFT_MASK (0x3f << MMCHS_CMD_INDX_SHIFT)
+#define MMCHS_CMD_CMD_TYPE_SHIFT 22
+#define MMCHS_CMD_DP_SHIFT 21
+#define MMCHS_CMD_DP (1 << MMCHS_CMD_DP_SHIFT)
+#define MMCHS_CMD_CICE_SHIFT 20
+#define MMCHS_CMD_CICE (1 << MMCHS_CMD_CICE_SHIFT)
+#define MMCHS_CMD_CCCE_SHIFT 19
+#define MMCHS_CMD_CCCE (1 << MMCHS_CMD_CCCE_SHIFT)
+#define MMCHS_CMD_RSP_TYPE_SHIFT 16
+#define MMCHS_CMD_RESP_NONE (0x0 << MMCHS_CMD_RSP_TYPE_SHIFT)
+#define MMCHS_CMD_RESP136 (0x1 << MMCHS_CMD_RSP_TYPE_SHIFT)
+#define MMCHS_CMD_RESP48 (0x2 << MMCHS_CMD_RSP_TYPE_SHIFT)
+#define MMCHS_CMD_RESP48B (0x3 << MMCHS_CMD_RSP_TYPE_SHIFT)
+#define MMCHS_CMD_MSBS (1 << 5)
+#define MMCHS_CMD_DDIR (1 << 4)
+#define MMCHS_CMD_ACEN (1 << 2)
+#define MMCHS_CMD_BCE (1 << 1)
+#define MMCHS_CMD_DE (1 << 0)
+#define MMCHS_RSP10 0x110
+#define MMCHS_RSP32 0x114
+#define MMCHS_RSP54 0x118
+#define MMCHS_RSP76 0x11C
+#define MMCHS_DATA 0x120
+#define MMCHS_PSTATE 0x124
+#define MMCHS_PSTATE_CLEV (1<<24)
+#define MMCHS_PSTATE_DLEV_SH 20
+#define MMCHS_PSTATE_DLEV_M (0xf << MMCHS_PSTATE_DLEV_SH)
+#define MMCHS_PSTATE_BRE (1<<11)
+#define MMCHS_PSTATE_BWE (1<<10)
+#define MMCHS_PSTATE_RTA (1<<9)
+#define MMCHS_PSTATE_WTA (1<<8)
+#define MMCHS_PSTATE_DLA (1<<2)
+#define MMCHS_PSTATE_DATI (1<<1)
+#define MMCHS_PSTATE_CMDI (1<<0)
+#define MMCHS_PSTATE_FMT "\20" \
+ "\x098_CLEV" \
+ "\x08b_BRE" \
+ "\x08a_BWE" \
+ "\x089_RTA" \
+ "\x088_WTA" \
+ "\x082_DLA" \
+ "\x081_DATI" \
+ "\x080_CMDI"
+#define MMCHS_HCTL 0x128
+#define MMCHS_HCTL_SDVS_SHIFT 9
+#define MMCHS_HCTL_SDVS_MASK (0x7<<MMCHS_HCTL_SDVS_SHIFT)
+#define MMCHS_HCTL_SDVS_V18 (0x5<<MMCHS_HCTL_SDVS_SHIFT)
+#define MMCHS_HCTL_SDVS_V30 (0x6<<MMCHS_HCTL_SDVS_SHIFT)
+#define MMCHS_HCTL_SDVS_V33 (0x7<<MMCHS_HCTL_SDVS_SHIFT)
+#define MMCHS_HCTL_SDBP (1<<8)
+#define MMCHS_HCTL_HSPE (1<<2)
+#define MMCHS_HCTL_DTW (1<<1)
+#define MMCHS_SYSCTL 0x12C
+#define MMCHS_SYSCTL_SRD (1<<26)
+#define MMCHS_SYSCTL_SRC (1<<25)
+#define MMCHS_SYSCTL_SRA (1<<24)
+#define MMCHS_SYSCTL_DTO_SH 16
+#define MMCHS_SYSCTL_DTO_MASK 0x000f0000
+#define MMCHS_SYSCTL_CLKD_SH 6
+#define MMCHS_SYSCTL_CLKD_MASK 0x0000ffc0
+#define MMCHS_SYSCTL_CEN (1<<2)
+#define MMCHS_SYSCTL_ICS (1<<1)
+#define MMCHS_SYSCTL_ICE (1<<0)
+#define MMCHS_STAT 0x130
+#define MMCHS_STAT_BADA (1<<29)
+#define MMCHS_STAT_CERR (1<<28)
+#define MMCHS_STAT_ACE (1<<24)
+#define MMCHS_STAT_DEB (1<<22)
+#define MMCHS_STAT_DCRC (1<<21)
+#define MMCHS_STAT_DTO (1<<20)
+#define MMCHS_STAT_CIE (1<<19)
+#define MMCHS_STAT_CEB (1<<18)
+#define MMCHS_STAT_CCRC (1<<17)
+#define MMCHS_STAT_CTO (1<<16)
+#define MMCHS_STAT_ERRI (1<<15)
+#define MMCHS_STAT_OBI (1<<9)
+#define MMCHS_STAT_CIRQ (1<<8)
+#define MMCHS_STAT_BRR (1<<5)
+#define MMCHS_STAT_BWR (1<<4)
+#define MMCHS_STAT_BGE (1<<2)
+#define MMCHS_STAT_TC (1<<1)
+#define MMCHS_STAT_CC (1<<0)
+#define MMCHS_STAT_FMT "\20" \
+ "\x09d_BADA" \
+ "\x09c_CERR" \
+ "\x098_ACE" \
+ "\x096_DEB" \
+ "\x095_DCRC" \
+ "\x094_DTO" \
+ "\x093_CIE" \
+ "\x092_CEB" \
+ "\x091_CCRC" \
+ "\x090_CTO" \
+ "\x08f_ERRI" \
+ "\x089_OBI" \
+ "\x088_CIRQ" \
+ "\x085_BRR" \
+ "\x084_BWR" \
+ "\x082_BGE" \
+ "\x081_TC" \
+ "\x080_CC"
+#define MMCHS_IE 0x134
+#define MMCHS_ISE 0x138
+#define MMCHS_AC12 0x13C
+#define MMCHS_CAPA 0x140
+#define MMCHS_CAPA_VS18 (1 << 26)
+#define MMCHS_CAPA_VS30 (1 << 25)
+#define MMCHS_CAPA_VS33 (1 << 24)
+#define MMCHS_CAPA_SRS (1 << 23)
+#define MMCHS_CAPA_DS (1 << 22)
+#define MMCHS_CAPA_HSS (1 << 21)
+#define MMCHS_CAPA_MBL_SHIFT 16
+#define MMCHS_CAPA_MBL_MASK (3 << MMCHS_CAPA_MBL_SHIFT)
+#define MMCHS_CUR_CAPA 0x148
+#define MMCHS_REV 0x1fc
+
+#define SDHC_COMMAND_TIMEOUT hz
+#define SDHC_BUFFER_TIMEOUT hz
+#define SDHC_TRANSFER_TIMEOUT hz
+
+void ommmc_attach(struct device *parent, struct device *self, void *args);
+
+struct ommmc_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ void *sc_ih; /* Interrupt handler */
+ uint32_t sc_flags;
+
+ struct device *sdmmc; /* generic SD/MMC device */
+ int clockbit; /* clock control bit */
+ uint32_t clkbase; /* base clock frequency in KHz */
+ int maxblklen; /* maximum block length */
+ int flags; /* flags for this host */
+ uint32_t ocr; /* OCR value from capabilities */
+ uint32_t intr_status; /* soft interrupt status */
+ uint32_t intr_error_status; /* */
+};
+
+
+/* Host controller functions called by the attachment driver. */
+int ommmc_host_found(struct ommmc_softc *, bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, int);
+void ommmc_power(int, void *);
+void ommmc_shutdown(void *);
+int ommmc_intr(void *);
+
+/* RESET MODES */
+#define MMC_RESET_DAT 1
+#define MMC_RESET_CMD 2
+#define MMC_RESET_ALL (MMC_RESET_CMD|MMC_RESET_DAT)
+
+/* flag values */
+#define SHF_USE_DMA 0x0001
+
+#define HREAD4(sc, reg) \
+ (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
+#define HWRITE4(sc, reg, val) \
+ bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+#define HSET4(sc, reg, bits) \
+ HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
+#define HCLR4(sc, reg, bits) \
+ HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
+
+int ommmc_host_reset(sdmmc_chipset_handle_t);
+uint32_t ommmc_host_ocr(sdmmc_chipset_handle_t);
+int ommmc_host_maxblklen(sdmmc_chipset_handle_t);
+int ommmc_card_detect(sdmmc_chipset_handle_t);
+int ommmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
+int ommmc_bus_clock(sdmmc_chipset_handle_t, int);
+int ommmc_bus_width(sdmmc_chipset_handle_t, int);
+void ommmc_card_intr_mask(sdmmc_chipset_handle_t, int);
+void ommmc_card_intr_ack(sdmmc_chipset_handle_t);
+void ommmc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
+int ommmc_start_command(struct ommmc_softc *, struct sdmmc_command *);
+int ommmc_wait_state(struct ommmc_softc *, uint32_t, uint32_t);
+int ommmc_soft_reset(struct ommmc_softc *, int);
+int ommmc_wait_intr(struct ommmc_softc *, int, int);
+void ommmc_transfer_data(struct ommmc_softc *, struct sdmmc_command *);
+void ommmc_read_data(struct ommmc_softc *, uint8_t *, int);
+void ommmc_write_data(struct ommmc_softc *, uint8_t *, int);
+
+/* #define SDHC_DEBUG */
+#ifdef SDHC_DEBUG
+int ommmcdebug = 20;
+#define DPRINTF(n,s) do { if ((n) <= ommmcdebug) printf s; } while (0)
+void ommmc_dump_regs(struct ommmc_softc *);
+#else
+#define DPRINTF(n,s) do {} while(0)
+#endif
+
+struct sdmmc_chip_functions ommmc_functions = {
+ /* host controller reset */
+ ommmc_host_reset,
+ /* host controller capabilities */
+ ommmc_host_ocr,
+ ommmc_host_maxblklen,
+ /* card detection */
+ ommmc_card_detect,
+ /* bus power and clock frequency */
+ ommmc_bus_power,
+ ommmc_bus_clock,
+ ommmc_bus_width,
+ /* command execution */
+ ommmc_exec_command,
+ /* card interrupt */
+ ommmc_card_intr_mask,
+ ommmc_card_intr_ack
+};
+
+struct cfdriver ommmc_cd = {
+ NULL, "ommmc", DV_DULL
+};
+
+struct cfattach ommmc_ca = {
+ sizeof(struct ommmc_softc), NULL, ommmc_attach
+};
+
+void
+ommmc_attach(struct device *parent, struct device *self, void *args)
+{
+ struct ommmc_softc *sc = (struct ommmc_softc *) self;
+ struct armv7_attach_args *aa = args;
+ struct sdmmcbus_attach_args saa;
+ uint32_t caps;
+
+ sc->sc_iot = aa->aa_iot;
+ if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
+ panic("%s: bus_space_map failed!", __func__);
+
+ printf("\n");
+
+ /* Enable ICLKEN, FCLKEN? */
+ prcm_enablemodule(PRCM_MMC0 + aa->aa_dev->unit);
+
+ sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_SDMMC,
+ ommmc_intr, sc, DEVNAME(sc));
+ if (sc->sc_ih == NULL) {
+ printf("%s: cannot map interrupt\n", DEVNAME(sc));
+ goto err;
+ }
+
+ /* Controller Voltage Capabilities Initialization */
+ HSET4(sc, MMCHS_CAPA, MMCHS_CAPA_VS18 | MMCHS_CAPA_VS30);
+
+#ifdef SDHC_DEBUG
+ ommmc_dump_regs(sc);
+#endif
+
+ /*
+ * Reset the host controller and enable interrupts.
+ */
+ ommmc_host_reset(sc);
+
+ /* Determine host capabilities. */
+ caps = HREAD4(sc, MMCHS_CAPA);
+
+#if 0
+ /* we want this !! */
+ /* Use DMA if the host system and the controller support it. */
+ if (usedma && ISSET(caps, SDHC_DMA_SUPPORT))
+ SET(sc->flags, SHF_USE_DMA);
+#endif
+
+ /*
+ * Determine the base clock frequency. (2.2.24)
+ */
+
+ sc->clkbase = 96 * 1000;
+#if 0
+ if (SDHC_BASE_FREQ_KHZ(caps) != 0)
+ sc->clkbase = SDHC_BASE_FREQ_KHZ(caps);
+ sc->clkbase = SDHC_BASE_FREQ_KHZ(caps);
+#endif
+ if (sc->clkbase == 0) {
+ /* The attachment driver must tell us. */
+ printf("%s: base clock frequency unknown\n", DEVNAME(sc));
+ goto err;
+ } else if (sc->clkbase < 10000 || sc->clkbase > 96000) {
+ /* SDHC 1.0 supports only 10-63 MHz. */
+ printf("%s: base clock frequency out of range: %u MHz\n",
+ DEVNAME(sc), sc->clkbase / 1000);
+ goto err;
+ }
+
+ /*
+ * XXX Set the data timeout counter value according to
+ * capabilities. (2.2.15)
+ */
+
+
+ /*
+ * Determine SD bus voltage levels supported by the controller.
+ */
+ if (caps & MMCHS_CAPA_VS18)
+ SET(sc->ocr, MMC_OCR_1_65V_1_95V);
+ if (caps & MMCHS_CAPA_VS30)
+ SET(sc->ocr, MMC_OCR_2_9V_3_0V | MMC_OCR_3_0V_3_1V);
+ if (caps & MMCHS_CAPA_VS33)
+ SET(sc->ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V);
+
+ /*
+ * Omap max block size is fixed (single buffer), could limit
+ * this to 512 for double buffering, but dont see the point.
+ */
+ switch ((caps & MMCHS_CAPA_MBL_MASK) >> MMCHS_CAPA_MBL_SHIFT) {
+ case 0:
+ sc->maxblklen = 512;
+ break;
+ case 1:
+ sc->maxblklen = 1024;
+ break;
+ case 2:
+ sc->maxblklen = 2048;
+ break;
+ default:
+ sc->maxblklen = 512;
+ printf("invalid capability blocksize in capa %08x,"
+ " trying 512\n", HREAD4(sc, MMCHS_CAPA));
+ }
+ /*
+ * MMC does not support blksize > 512 yet
+ */
+ sc->maxblklen = 512;
+ /*
+ * Attach the generic SD/MMC bus driver. (The bus driver must
+ * not invoke any chipset functions before it is attached.)
+ */
+ bzero(&saa, sizeof(saa));
+ saa.saa_busname = "sdmmc";
+ saa.sct = &ommmc_functions;
+ saa.sch = sc;
+ saa.caps = SMC_CAPS_4BIT_MODE;
+ if (caps & MMCHS_CAPA_HSS)
+ saa.caps |= SMC_CAPS_MMC_HIGHSPEED;
+
+ sc->sdmmc = config_found(&sc->sc_dev, &saa, NULL);
+ if (sc->sdmmc == NULL) {
+ printf("%s: can't attach sdmmc\n", DEVNAME(sc));
+ goto err;
+ }
+
+ return;
+err:
+ if (sc->sc_ih != NULL)
+ arm_intr_disestablish(sc->sc_ih);
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, aa->aa_dev->mem[0].size);
+}
+
+
+/*
+ * Power hook established by or called from attachment driver.
+ */
+void
+ommmc_power(int why, void *arg)
+{
+#if 0
+ struct ommmc_softc *sc = arg;
+ int n, i;
+#endif
+
+ switch(why) {
+ case DVACT_SUSPEND:
+ /* XXX poll for command completion or suspend command
+ * in progress */
+
+ /* Save the host controller state. */
+#if 0
+ for (i = 0; i < sizeof sc->regs; i++)
+ sc->regs[i] = HREAD1(sc, i);
+#endif
+ break;
+
+ case DVACT_RESUME:
+ /* Restore the host controller state. */
+#if 0
+ (void)ommmc_host_reset(sc);
+ for (i = 0; i < sizeof sc->regs; i++)
+ HWRITE1(sc, i, sc->regs[i]);
+#endif
+ break;
+ }
+}
+
+/*
+ * Shutdown hook established by or called from attachment driver.
+ */
+void
+ommmc_shutdown(void *arg)
+{
+ struct ommmc_softc *sc = arg;
+
+ /* XXX chip locks up if we don't disable it before reboot. */
+ (void)ommmc_host_reset(sc);
+}
+
+/*
+ * Reset the host controller. Called during initialization, when
+ * cards are removed, upon resume, and during error recovery.
+ */
+int
+ommmc_host_reset(sdmmc_chipset_handle_t sch)
+{
+ struct ommmc_softc *sc = sch;
+ uint32_t imask;
+ int error;
+ int s;
+
+ s = splsdmmc();
+
+ /* Disable all interrupts. */
+ HWRITE4(sc, MMCHS_IE, 0);
+ HWRITE4(sc, MMCHS_ISE, 0);
+
+ /*
+ * Reset the entire host controller and wait up to 100ms for
+ * the controller to clear the reset bit.
+ */
+ if ((error = ommmc_soft_reset(sc, MMCHS_SYSCTL_SRA)) != 0) {
+ splx(s);
+ return (error);
+ }
+
+#if 0
+ HSET4(sc, MMCHS_CON, MMCHS_CON_INIT);
+ HWRITE4(sc, MMCHS_CMD, 0);
+ delay(100); /* should delay 1ms */
+
+ HWRITE4(sc, MMCHS_STAT, MMCHS_STAT_CC);
+ HCLR4(sc, MMCHS_CON, MMCHS_CON_INIT);
+ HWRITE4(sc, MMCHS_STAT, ~0);
+#endif
+
+
+ /* Set data timeout counter value to max for now. */
+ HSET4(sc, MMCHS_SYSCTL, 0xe << MMCHS_SYSCTL_DTO_SH);
+
+ /* Enable interrupts. */
+ imask = MMCHS_STAT_BRR | MMCHS_STAT_BWR | MMCHS_STAT_BGE |
+ MMCHS_STAT_TC | MMCHS_STAT_CC;
+
+ imask |= MMCHS_STAT_BADA | MMCHS_STAT_CERR | MMCHS_STAT_DEB |
+ MMCHS_STAT_DCRC | MMCHS_STAT_DTO | MMCHS_STAT_CIE |
+ MMCHS_STAT_CEB | MMCHS_STAT_CCRC | MMCHS_STAT_CTO;
+
+ HWRITE4(sc, MMCHS_IE, imask);
+ HWRITE4(sc, MMCHS_ISE, imask);
+
+ splx(s);
+ return (0);
+}
+
+uint32_t
+ommmc_host_ocr(sdmmc_chipset_handle_t sch)
+{
+ struct ommmc_softc *sc = sch;
+ return (sc->ocr);
+}
+
+int
+ommmc_host_maxblklen(sdmmc_chipset_handle_t sch)
+{
+ struct ommmc_softc *sc = sch;
+ return (sc->maxblklen);
+}
+
+/*
+ * Return non-zero if the card is currently inserted.
+ */
+int
+ommmc_card_detect(sdmmc_chipset_handle_t sch)
+{
+ struct ommmc_softc *sc = sch;
+ return !ISSET(HREAD4(sc, MMCHS_SYSTEST), MMCHS_SYSTEST_SDCD) ?
+ 1 : 0;
+}
+
+/*
+ * Set or change SD bus voltage and enable or disable SD bus power.
+ * Return zero on success.
+ */
+int
+ommmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
+{
+ struct ommmc_softc *sc = sch;
+ uint32_t vdd;
+ uint32_t reg;
+ int s;
+
+ s = splsdmmc();
+
+ /*
+ * Disable bus power before voltage change.
+ */
+ HCLR4(sc, MMCHS_HCTL, MMCHS_HCTL_SDBP);
+
+ /* If power is disabled, reset the host and return now. */
+ if (ocr == 0) {
+ splx(s);
+ (void)ommmc_host_reset(sc);
+ return (0);
+ }
+
+ /*
+ * Select the maximum voltage according to capabilities.
+ */
+ ocr &= sc->ocr;
+
+ if (ISSET(ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V))
+ vdd = MMCHS_HCTL_SDVS_V33;
+ else if (ISSET(ocr, MMC_OCR_2_9V_3_0V | MMC_OCR_3_0V_3_1V))
+ vdd = MMCHS_HCTL_SDVS_V30;
+ else if (ISSET(ocr, MMC_OCR_1_65V_1_95V))
+ vdd = MMCHS_HCTL_SDVS_V18;
+ else {
+ /* Unsupported voltage level requested. */
+ splx(s);
+ return (EINVAL);
+ }
+
+ /*
+ * Enable bus power. Wait at least 1 ms (or 74 clocks) plus
+ * voltage ramp until power rises.
+ */
+ reg = HREAD4(sc, MMCHS_HCTL);
+ reg &= ~MMCHS_HCTL_SDVS_MASK;
+ reg |= vdd;
+ HWRITE4(sc, MMCHS_HCTL, reg);
+
+ HSET4(sc, MMCHS_HCTL, MMCHS_HCTL_SDBP);
+ delay(10000); /* XXX */
+
+ /*
+ * The host system may not power the bus due to battery low,
+ * etc. In that case, the host controller should clear the
+ * bus power bit.
+ */
+ if (!ISSET(HREAD4(sc, MMCHS_HCTL), MMCHS_HCTL_SDBP)) {
+ splx(s);
+ return (ENXIO);
+ }
+
+ splx(s);
+ return (0);
+}
+
+/*
+ * Return the smallest possible base clock frequency divisor value
+ * for the CLOCK_CTL register to produce `freq' (KHz).
+ */
+static int
+ommmc_clock_divisor(struct ommmc_softc *sc, uint32_t freq)
+{
+ int div;
+ uint32_t maxclk = MMCHS_SYSCTL_CLKD_MASK>>MMCHS_SYSCTL_CLKD_SH;
+
+ for (div = 1; div <= maxclk; div++)
+ if ((sc->clkbase / div) <= freq) {
+ return (div);
+ }
+
+ printf("divisor failure\n");
+ /* No divisor found. */
+ return (-1);
+}
+
+/*
+ * Set or change SDCLK frequency or disable the SD clock.
+ * Return zero on success.
+ */
+int
+ommmc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
+{
+ int error = 0;
+ struct ommmc_softc *sc = sch;
+ uint32_t reg;
+ int s;
+ int div;
+ int timo;
+
+ s = splsdmmc();
+
+ /* Must not stop the clock if commands are in progress. */
+ for (timo = 1000; timo > 0; timo--) {
+ if (!ISSET(HREAD4(sc, MMCHS_PSTATE),
+ MMCHS_PSTATE_CMDI|MMCHS_PSTATE_DATI))
+ break;
+ delay(10);
+ }
+ if (timo == 0) {
+ error = ETIMEDOUT;
+ goto ret;
+ }
+
+ /*
+ * Stop SD clock before changing the frequency.
+ */
+ HCLR4(sc, MMCHS_SYSCTL, MMCHS_SYSCTL_CEN);
+ if (freq == SDMMC_SDCLK_OFF)
+ goto ret;
+
+ /*
+ * Set the minimum base clock frequency divisor.
+ */
+ if ((div = ommmc_clock_divisor(sc, freq)) < 0) {
+ /* Invalid base clock frequency or `freq' value. */
+ error = EINVAL;
+ goto ret;
+ }
+ reg = HREAD4(sc, MMCHS_SYSCTL);
+ reg &= ~MMCHS_SYSCTL_CLKD_MASK;
+ reg |= div << MMCHS_SYSCTL_CLKD_SH;
+ HWRITE4(sc, MMCHS_SYSCTL, reg);
+
+ /*
+ * Start internal clock. Wait 10ms for stabilization.
+ */
+ HSET4(sc, MMCHS_SYSCTL, MMCHS_SYSCTL_ICE);
+ for (timo = 1000; timo > 0; timo--) {
+ if (ISSET(HREAD4(sc, MMCHS_SYSCTL), MMCHS_SYSCTL_ICS))
+ break;
+ delay(10);
+ }
+ if (timo == 0) {
+ error = ETIMEDOUT;
+ goto ret;
+ }
+
+ /*
+ * Enable SD clock.
+ */
+ HSET4(sc, MMCHS_SYSCTL, MMCHS_SYSCTL_CEN);
+ret:
+ splx(s);
+ return (error);
+}
+
+int
+ommmc_bus_width(sdmmc_chipset_handle_t sch, int width)
+{
+ struct ommmc_softc *sc = sch;
+ int s;
+
+ if (width != 1 && width != 4 && width != 8)
+ return (1);
+
+ s = splsdmmc();
+
+ if (width == 8)
+ HSET4(sc, MMCHS_CON, MMCHS_CON_DW8);
+ else
+ HCLR4(sc, MMCHS_CON, MMCHS_CON_DW8);
+
+ if (width == 4)
+ HSET4(sc, MMCHS_HCTL, MMCHS_HCTL_DTW);
+ else if (width == 1)
+ HCLR4(sc, MMCHS_HCTL, MMCHS_HCTL_DTW);
+
+ splx(s);
+
+ return (0);
+}
+
+void
+ommmc_card_intr_mask(sdmmc_chipset_handle_t sch, int enable)
+{
+ /* - this is SDIO card interrupt */
+ struct ommmc_softc *sc = sch;
+
+ if (enable) {
+ HSET4(sc, MMCHS_IE, MMCHS_STAT_CIRQ);
+ HSET4(sc, MMCHS_ISE, MMCHS_STAT_CIRQ);
+ } else {
+ HCLR4(sc, MMCHS_IE, MMCHS_STAT_CIRQ);
+ HCLR4(sc, MMCHS_ISE, MMCHS_STAT_CIRQ);
+ }
+}
+
+void
+ommmc_card_intr_ack(sdmmc_chipset_handle_t sch)
+{
+ struct ommmc_softc *sc = sch;
+
+ HWRITE4(sc, MMCHS_STAT, MMCHS_STAT_CIRQ);
+}
+
+int
+ommmc_wait_state(struct ommmc_softc *sc, uint32_t mask, uint32_t value)
+{
+ uint32_t state;
+ int timeout;
+
+ state = HREAD4(sc, MMCHS_PSTATE);
+ DPRINTF(3,("%s: wait_state %x %x %x(state=%b)\n", DEVNAME(sc),
+ mask, value, state, state, MMCHS_PSTATE_FMT));
+ for (timeout = 1000; timeout > 0; timeout--) {
+ if (((state = HREAD4(sc, MMCHS_PSTATE)) & mask) == value)
+ return (0);
+ delay(10);
+ }
+ DPRINTF(0,("%s: timeout waiting for %x (state=%b)\n", DEVNAME(sc),
+ value, state, MMCHS_PSTATE_FMT));
+ return (ETIMEDOUT);
+}
+
+void
+ommmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
+{
+ struct ommmc_softc *sc = sch;
+ int error;
+
+ /*
+ * Start the MMC command, or mark `cmd' as failed and return.
+ */
+ error = ommmc_start_command(sc, cmd);
+ if (error != 0) {
+ cmd->c_error = error;
+ SET(cmd->c_flags, SCF_ITSDONE);
+ return;
+ }
+
+ /*
+ * Wait until the command phase is done, or until the command
+ * is marked done for any other reason.
+ */
+ if (!ommmc_wait_intr(sc, MMCHS_STAT_CC, SDHC_COMMAND_TIMEOUT)) {
+ cmd->c_error = ETIMEDOUT;
+ SET(cmd->c_flags, SCF_ITSDONE);
+ return;
+ }
+
+ /*
+ * The host controller removes bits [0:7] from the response
+ * data (CRC) and we pass the data up unchanged to the bus
+ * driver (without padding).
+ */
+ if (cmd->c_error == 0 && ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
+ if (ISSET(cmd->c_flags, SCF_RSP_136)) {
+ uint32_t v0,v1,v2,v3;
+ v0 = HREAD4(sc, MMCHS_RSP10);
+ v1 = HREAD4(sc, MMCHS_RSP32);
+ v2 = HREAD4(sc, MMCHS_RSP54);
+ v3 = HREAD4(sc, MMCHS_RSP76);
+
+ cmd->c_resp[0] = (v0 >> 8) | ((v1 & 0xff) << 24);
+ cmd->c_resp[1] = (v1 >> 8) | ((v2 & 0xff) << 24);
+ cmd->c_resp[2] = (v2 >> 8) | ((v3 & 0xff) << 24);
+ cmd->c_resp[3] = v3 >> 8;
+#ifdef SDHC_DEBUG
+ printf("resp[0] 0x%08x\nresp[1] 0x%08x\nresp[2] 0x%08x\nresp[3] 0x%08x\n", cmd->c_resp[0], cmd->c_resp[1], cmd->c_resp[2], cmd->c_resp[3]);
+#endif
+ } else {
+ cmd->c_resp[0] = HREAD4(sc, MMCHS_RSP10);
+#ifdef SDHC_DEBUG
+ printf("resp[0] 0x%08x\n", cmd->c_resp[0]);
+#endif
+ }
+ }
+
+ /*
+ * If the command has data to transfer in any direction,
+ * execute the transfer now.
+ */
+ if (cmd->c_error == 0 && cmd->c_data != NULL)
+ ommmc_transfer_data(sc, cmd);
+
+#if 0
+ /* Turn off the LED. */
+ HCLR1(sc, SDHC_HOST_CTL, SDHC_LED_ON);
+#endif
+
+ DPRINTF(1,("%s: cmd %u done (flags=%#x error=%d)\n",
+ DEVNAME(sc), cmd->c_opcode, cmd->c_flags, cmd->c_error));
+ SET(cmd->c_flags, SCF_ITSDONE);
+}
+
+int
+ommmc_start_command(struct ommmc_softc *sc, struct sdmmc_command *cmd)
+{
+ uint32_t blksize = 0;
+ uint32_t blkcount = 0;
+ uint32_t command;
+ int error;
+ int s;
+
+ DPRINTF(1,("%s: start cmd %u arg=%#x data=%p dlen=%d flags=%#x "
+ "proc=\"%s\"\n", DEVNAME(sc), cmd->c_opcode, cmd->c_arg,
+ cmd->c_data, cmd->c_datalen, cmd->c_flags, curproc ?
+ curproc->p_comm : ""));
+
+ /*
+ * The maximum block length for commands should be the minimum
+ * of the host buffer size and the card buffer size. (1.7.2)
+ */
+
+ /* Fragment the data into proper blocks. */
+ if (cmd->c_datalen > 0) {
+ blksize = MIN(cmd->c_datalen, cmd->c_blklen);
+ blkcount = cmd->c_datalen / blksize;
+ if (cmd->c_datalen % blksize > 0) {
+ /* XXX: Split this command. (1.7.4) */
+ printf("%s: data not a multiple of %d bytes\n",
+ DEVNAME(sc), blksize);
+ return (EINVAL);
+ }
+ }
+
+ /* Check limit imposed by 9-bit block count. (1.7.2) */
+ if (blkcount > MMCHS_BLK_NBLK_MAX) {
+ printf("%s: too much data\n", DEVNAME(sc));
+ return (EINVAL);
+ }
+
+ /* Prepare transfer mode register value. (2.2.5) */
+ command = 0;
+ if (ISSET(cmd->c_flags, SCF_CMD_READ))
+ command |= MMCHS_CMD_DDIR;
+ if (blkcount > 0) {
+ command |= MMCHS_CMD_BCE;
+ if (blkcount > 1) {
+ command |= MMCHS_CMD_MSBS;
+ /* XXX only for memory commands? */
+ command |= MMCHS_CMD_ACEN;
+ }
+ }
+#ifdef notyet
+ if (ISSET(sc->flags, SHF_USE_DMA))
+ command |= MMCHS_CMD_DE;
+#endif
+
+ /*
+ * Prepare command register value. (2.2.6)
+ */
+ command |= (cmd->c_opcode << MMCHS_CMD_INDX_SHIFT) &
+ MMCHS_CMD_INDX_SHIFT_MASK;
+
+ if (ISSET(cmd->c_flags, SCF_RSP_CRC))
+ command |= MMCHS_CMD_CCCE;
+ if (ISSET(cmd->c_flags, SCF_RSP_IDX))
+ command |= MMCHS_CMD_CICE;
+ if (cmd->c_data != NULL)
+ command |= MMCHS_CMD_DP;
+
+ if (!ISSET(cmd->c_flags, SCF_RSP_PRESENT))
+ command |= MMCHS_CMD_RESP_NONE;
+ else if (ISSET(cmd->c_flags, SCF_RSP_136))
+ command |= MMCHS_CMD_RESP136;
+ else if (ISSET(cmd->c_flags, SCF_RSP_BSY))
+ command |= MMCHS_CMD_RESP48B;
+ else
+ command |= MMCHS_CMD_RESP48;
+
+ /* Wait until command and data inhibit bits are clear. (1.5) */
+ if ((error = ommmc_wait_state(sc, MMCHS_PSTATE_CMDI, 0)) != 0)
+ return (error);
+
+ s = splsdmmc();
+
+#if 0
+ /* Alert the user not to remove the card. */
+ HSET1(sc, SDHC_HOST_CTL, SDHC_LED_ON);
+#endif
+
+ /* XXX: Set DMA start address if SHF_USE_DMA is set. */
+
+ DPRINTF(1,("%s: cmd=%#x blksize=%d blkcount=%d\n",
+ DEVNAME(sc), command, blksize, blkcount));
+
+ /*
+ * Start a CPU data transfer. Writing to the high order byte
+ * of the SDHC_COMMAND register triggers the SD command. (1.5)
+ */
+ HWRITE4(sc, MMCHS_BLK, (blkcount << MMCHS_BLK_NBLK_SHIFT) |
+ (blksize << MMCHS_BLK_BLEN_SHIFT));
+ HWRITE4(sc, MMCHS_ARG, cmd->c_arg);
+ HWRITE4(sc, MMCHS_CMD, command);
+
+ splx(s);
+ return (0);
+}
+
+void
+ommmc_transfer_data(struct ommmc_softc *sc, struct sdmmc_command *cmd)
+{
+ uint8_t *datap = cmd->c_data;
+ int i, datalen;
+ int mask;
+ int error;
+
+ mask = ISSET(cmd->c_flags, SCF_CMD_READ) ?
+ MMCHS_PSTATE_BRE : MMCHS_PSTATE_BWE;
+ error = 0;
+ datalen = cmd->c_datalen;
+
+ DPRINTF(1,("%s: resp=%#x datalen=%d\n", DEVNAME(sc),
+ MMC_R1(cmd->c_resp), datalen));
+
+ while (datalen > 0) {
+ if (!ommmc_wait_intr(sc, MMCHS_STAT_BRR| MMCHS_STAT_BWR,
+ SDHC_BUFFER_TIMEOUT)) {
+ error = ETIMEDOUT;
+ break;
+ }
+
+ if ((error = ommmc_wait_state(sc, mask, mask)) != 0)
+ break;
+
+ i = MIN(datalen, cmd->c_blklen);
+ if (ISSET(cmd->c_flags, SCF_CMD_READ))
+ ommmc_read_data(sc, datap, i);
+ else
+ ommmc_write_data(sc, datap, i);
+
+ datap += i;
+ datalen -= i;
+ }
+
+ if (error == 0 && !ommmc_wait_intr(sc, MMCHS_STAT_TC,
+ SDHC_TRANSFER_TIMEOUT))
+ error = ETIMEDOUT;
+
+ if (error != 0)
+ cmd->c_error = error;
+ SET(cmd->c_flags, SCF_ITSDONE);
+
+ DPRINTF(1,("%s: data transfer done (error=%d)\n",
+ DEVNAME(sc), cmd->c_error));
+}
+
+void
+ommmc_read_data(struct ommmc_softc *sc, uint8_t *datap, int datalen)
+{
+ while (datalen > 3) {
+ *(uint32_t *)datap = HREAD4(sc, MMCHS_DATA);
+ datap += 4;
+ datalen -= 4;
+ }
+ if (datalen > 0) {
+ uint32_t rv = HREAD4(sc, MMCHS_DATA);
+ do {
+ *datap++ = rv & 0xff;
+ rv = rv >> 8;
+ } while (--datalen > 0);
+ }
+}
+
+void
+ommmc_write_data(struct ommmc_softc *sc, uint8_t *datap, int datalen)
+{
+ while (datalen > 3) {
+ DPRINTF(3,("%08x\n", *(uint32_t *)datap));
+ HWRITE4(sc, MMCHS_DATA, *((uint32_t *)datap));
+ datap += 4;
+ datalen -= 4;
+ }
+ if (datalen > 0) {
+ uint32_t rv = *datap++;
+ if (datalen > 1)
+ rv |= *datap++ << 8;
+ if (datalen > 2)
+ rv |= *datap++ << 16;
+ DPRINTF(3,("rv %08x\n", rv));
+ HWRITE4(sc, MMCHS_DATA, rv);
+ }
+}
+
+/* Prepare for another command. */
+int
+ommmc_soft_reset(struct ommmc_softc *sc, int mask)
+{
+
+ int timo;
+
+ DPRINTF(1,("%s: software reset reg=%#x\n", DEVNAME(sc), mask));
+
+ HSET4(sc, MMCHS_SYSCTL, mask);
+ delay(10);
+ for (timo = 1000; timo > 0; timo--) {
+ if (!ISSET(HREAD4(sc, MMCHS_SYSCTL), mask))
+ break;
+ delay(10);
+ }
+ if (timo == 0) {
+ DPRINTF(1,("%s: timeout reg=%#x\n", DEVNAME(sc),
+ HREAD4(sc, MMCHS_SYSCTL)));
+ return (ETIMEDOUT);
+ }
+
+ return (0);
+}
+
+int
+ommmc_wait_intr(struct ommmc_softc *sc, int mask, int timo)
+{
+ int status;
+ int s;
+
+ mask |= MMCHS_STAT_ERRI;
+
+ s = splsdmmc();
+ status = sc->intr_status & mask;
+ while (status == 0) {
+ if (tsleep(&sc->intr_status, PWAIT, "hcintr", timo)
+ == EWOULDBLOCK) {
+ status |= MMCHS_STAT_ERRI;
+ break;
+ }
+ status = sc->intr_status & mask;
+ }
+ sc->intr_status &= ~status;
+
+ DPRINTF(2,("%s: intr status %#x error %#x\n", DEVNAME(sc), status,
+ sc->intr_error_status));
+
+ /* Command timeout has higher priority than command complete. */
+ if (ISSET(status, MMCHS_STAT_ERRI)) {
+ sc->intr_error_status = 0;
+ (void)ommmc_soft_reset(sc, MMCHS_SYSCTL_SRC|MMCHS_SYSCTL_SRD);
+ status = 0;
+ }
+
+ splx(s);
+ return (status);
+}
+
+/*
+ * Established by attachment driver at interrupt priority IPL_SDMMC.
+ */
+int
+ommmc_intr(void *arg)
+{
+ struct ommmc_softc *sc = arg;
+
+ uint32_t status;
+
+ /* Find out which interrupts are pending. */
+ status = HREAD4(sc, MMCHS_STAT);
+
+ /* Acknowledge the interrupts we are about to handle. */
+ HWRITE4(sc, MMCHS_STAT, status);
+ DPRINTF(2,("%s: interrupt status=%b\n", DEVNAME(sc),
+ status, MMCHS_STAT_FMT));
+
+ /*
+ * Service error interrupts.
+ */
+ if (ISSET(status, MMCHS_STAT_ERRI)) {
+ if (ISSET(status, MMCHS_STAT_CTO|
+ MMCHS_STAT_DTO)) {
+ sc->intr_status |= status;
+ sc->intr_error_status |= status & 0xffff0000;
+ wakeup(&sc->intr_status);
+ }
+ }
+
+#if 0
+ /*
+ * Wake up the sdmmc event thread to scan for cards.
+ */
+ if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION))
+ ommmc_needs_discover(sc->sdmmc);
+#endif
+
+ /*
+ * Wake up the blocking process to service command
+ * related interrupt(s).
+ */
+ if (ISSET(status, MMCHS_STAT_BRR|
+ MMCHS_STAT_BWR|MMCHS_STAT_TC|
+ MMCHS_STAT_CC)) {
+ sc->intr_status |= status;
+ wakeup(&sc->intr_status);
+ }
+
+ /*
+ * Service SD card interrupts.
+ */
+ if (ISSET(status, MMCHS_STAT_CIRQ)) {
+ DPRINTF(0,("%s: card interrupt\n", DEVNAME(sc)));
+ HCLR4(sc, MMCHS_STAT, MMCHS_STAT_CIRQ);
+ sdmmc_card_intr(sc->sdmmc);
+ }
+ return 1;
+}
+
+#ifdef SDHC_DEBUG
+void
+ommmc_dump_regs(struct ommmc_softc *sc)
+{
+}
+#endif
--- /dev/null
+/* $OpenBSD: omohci.c,v 1.3 2014/05/19 13:11:31 mpi Exp $ */
+
+/*
+ * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/timeout.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+
+#include <dev/usb/ohcireg.h>
+#include <dev/usb/ohcivar.h>
+#include <armv7/omap/prcmvar.h>
+
+#define HOSTUEADDR 0x0E0
+#define HOSTUESTATUS 0x0E4
+#define HOSTTIMEOUTCTRL 0x0E8
+#define HOSTREVISION 0x0EC
+#define WHM_REVID_REGISTER 0x0F4
+#define WHM_TEST_OBSV 0x0F8
+#define WHM_TEST_CTL 0x0FC
+#define HHC_TEST_CFG 0x100
+#define HHC_TEST_CTL 0x104
+#define HHC_TEST_OBSV 0x108
+#define REVDEV 0x200 /* 16 bit */
+#define EP_NUM 0x204 /* 16 bit */
+#define DATA 0x208 /* 16 bit */
+#define CTRL 0x20C /* 16 bit */
+#define STAT_FLG 0x210 /* 16 bit */
+#define RXFSTAT 0x214 /* 16 bit */
+#define SYSCON1 0x218 /* 16 bit */
+#define SYSCON2 0x21C /* 16 bit */
+#define DEVSTAT 0x220 /* 16 bit */
+#define SOFREG 0x224 /* 16 bit */
+#define IRQ_EN 0x228 /* 16 bit */
+#define DMA_IRQ_EN 0x22C /* 16 bit */
+#define IRQ_SRC 0x230 /* 16 bit */
+#define EPN_STAT 0x234 /* 16 bit */
+#define DMAN_STAT 0x238 /* 16 bit */
+#define RXDMA_CFG 0x240 /* 16 bit */
+#define TXDMA_CFG 0x244 /* 16 bit */
+
+#define TXDMA0 0x250
+#define TXDMA1 0x254
+#define TXDMA2 0x258
+#define RXDMA0 0x260
+#define RXDMA1 0x264
+#define RXDMA2 0x268
+
+#define EP0 0x280
+#define EP_RX(x) 0x280 + (x * 4)
+#define EP_TX(x) 0x2C0 + (x * 4)
+
+#define OTG_REV 0x300
+#define OTG_SYSCON_1 0x304
+#define OTG_SYSCON_2 0x308
+#define OTG_SYSCON2_OTG_EN 0x80000000
+#define OTG_SYSCON2_UHOST_EN 0x00000100
+#define OTG_SYSCON2_MODE_DISABLED 0x00000000
+#define OTG_SYSCON2_MODE_CLIENT 0x00000001
+#define OTG_SYSCON2_MODE_HOST 0x00000004
+#define OTG_CTRL 0x30C
+#if 0
+#define OTG_IRQ_EN 0x310 /* 16 bit */
+#define OTG_IRQ_SRC 0x314 /* 16 bit */
+#define OTG_OUTCTRL 0x318 /* 16 bit */
+#define OTG_TEST 0x320 /* 16 bit */
+#endif
+#define OTG_VC 0x3FC
+
+
+int omohci_match(struct device *, void *, void *);
+void omohci_attach(struct device *, struct device *, void *);
+int omohci_detach(struct device *, int);
+int omohci_activate(struct device *, int);
+
+struct omohci_softc {
+ struct ohci_softc sc;
+ void *sc_ihc0;
+ void *sc_ihc1;
+ void *sc_ihc2;
+ void *sc_ih0;
+ void *sc_ih1;
+ void *sc_ihotg;
+};
+
+void omohci_enable(struct omohci_softc *);
+void omohci_disable(struct omohci_softc *);
+
+struct cfattach omohci_ca = {
+ sizeof (struct omohci_softc), omohci_match, omohci_attach,
+ omohci_detach, omohci_detach
+};
+
+int
+omohci_match(struct device *parent, void *match, void *aux)
+{
+#if 0
+ if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) != CPU_ID_PXA27X)
+ return (0);
+#endif
+
+ return (1);
+}
+
+void
+omohci_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct omohci_softc *sc = (struct omohci_softc *)self;
+ struct ahb_attach_args *aa = aux;
+ usbd_status r;
+
+ sc->sc.iot = aa->aa_iot;
+ sc->sc.sc_bus.dmatag = aa->aa_dmat;
+ sc->sc_ih0 = NULL;
+ sc->sc_ih1 = NULL;
+ sc->sc_ihc0 = NULL;
+ sc->sc_ihc1 = NULL;
+ sc->sc_ihc2 = NULL;
+ sc->sc_ihotg = NULL;
+ sc->sc.sc_size = 0;
+
+ /* Map I/O space */
+ if (bus_space_map(sc->sc.iot, aa->aa_addr, aa->aa_size, 0,
+ &sc->sc.ioh)) {
+ printf(": cannot map mem space\n");
+ return;
+ }
+ sc->sc.sc_size = aa->aa_size;
+
+ /* XXX copied from ohci_pci.c. needed? */
+ bus_space_barrier(sc->sc.iot, sc->sc.ioh, 0, sc->sc.sc_size,
+ BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
+
+#if 0
+ /* start the usb clock */
+ pxa2x0_clkman_config(CKEN_USBHC, 1);
+#endif
+ omohci_enable(sc);
+
+ /* Disable interrupts, so we don't get any spurious ones. */
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE,
+ OHCI_MIE);
+
+ sc->sc_ihc0 = arm_intr_establish(aa->aa_intr, IPL_USB,
+ ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
+ sc->sc_ihc1 = arm_intr_establish(aa->aa_intr+1, IPL_USB,
+ ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
+ sc->sc_ihc2 = arm_intr_establish(aa->aa_intr+2, IPL_USB,
+ ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
+ sc->sc_ih0 = arm_intr_establish(aa->aa_intr+3, IPL_USB,
+ ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
+ sc->sc_ih1 = arm_intr_establish(aa->aa_intr+4, IPL_USB,
+ ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
+ sc->sc_ihotg = arm_intr_establish(aa->aa_intr+5, IPL_USB,
+ ohci_intr, &sc->sc, sc->sc.sc_bus.bdev.dv_xname);
+ if (sc->sc_ih0 == NULL ||
+ sc->sc_ih1 == NULL ||
+ sc->sc_ihc0 == NULL ||
+ sc->sc_ihc1 == NULL ||
+ sc->sc_ihc2 == NULL ||
+ sc->sc_ihotg == NULL) {
+ printf(": unable to establish interrupt\n");
+ omohci_disable(sc);
+#if 0
+ pxa2x0_clkman_config(CKEN_USBHC, 0);
+#endif
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ sc->sc.sc_size = 0;
+ return;
+ }
+
+ prcm_enablemodule(PRCM_USB);
+
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, OTG_SYSCON_2,
+ OTG_SYSCON2_UHOST_EN | OTG_SYSCON2_MODE_HOST);
+
+ strlcpy(sc->sc.sc_vendor, "OMAP24xx", sizeof(sc->sc.sc_vendor));
+ r = ohci_init(&sc->sc);
+ if (r != USBD_NORMAL_COMPLETION) {
+ printf("%s: init failed, error=%d\n",
+ sc->sc.sc_bus.bdev.dv_xname, r);
+ arm_intr_disestablish(sc->sc_ih0);
+ arm_intr_disestablish(sc->sc_ih1);
+ arm_intr_disestablish(sc->sc_ihc0);
+ arm_intr_disestablish(sc->sc_ihc1);
+ arm_intr_disestablish(sc->sc_ihc2);
+ arm_intr_disestablish(sc->sc_ihotg);
+ sc->sc_ih0 = NULL;
+ sc->sc_ih1 = NULL;
+ sc->sc_ihc0 = NULL;
+ sc->sc_ihc1 = NULL;
+ sc->sc_ihc2 = NULL;
+ sc->sc_ihotg = NULL;
+ omohci_disable(sc);
+#if 0
+ pxa2x0_clkman_config(CKEN_USBHC, 0);
+#endif
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ sc->sc.sc_size = 0;
+ return;
+ }
+
+ config_found(self, &sc->sc.sc_bus, usbctlprint);
+}
+
+int
+omohci_detach(struct device *self, int flags)
+{
+ struct omohci_softc *sc = (struct omohci_softc *)self;
+ int rv;
+
+ rv = ohci_detach(self, flags);
+ if (rv)
+ return (rv);
+
+ if (sc->sc_ih0 != NULL) {
+ arm_intr_disestablish(sc->sc_ih0);
+ arm_intr_disestablish(sc->sc_ih1);
+ arm_intr_disestablish(sc->sc_ihc0);
+ arm_intr_disestablish(sc->sc_ihc1);
+ arm_intr_disestablish(sc->sc_ihc2);
+ arm_intr_disestablish(sc->sc_ihotg);
+ sc->sc_ih0 = NULL;
+ sc->sc_ih1 = NULL;
+ sc->sc_ihc0 = NULL;
+ sc->sc_ihc1 = NULL;
+ sc->sc_ihc2 = NULL;
+ sc->sc_ihotg = NULL;
+ }
+
+ omohci_disable(sc);
+
+ /* stop clock */
+#if 0
+ pxa2x0_clkman_config(CKEN_USBHC, 0);
+#endif
+
+ if (sc->sc.sc_size) {
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ sc->sc.sc_size = 0;
+ }
+
+ return (0);
+}
+
+
+int
+omohci_activate(struct device *self, int act)
+{
+ struct omohci_softc *sc = (struct omohci_softc *)self;
+
+ switch (act) {
+ case DVACT_SUSPEND:
+ sc->sc.sc_bus.use_polling++;
+ ohci_power(why, &sc->sc);
+#if 0
+ pxa2x0_clkman_config(CKEN_USBHC, 0);
+#endif
+ sc->sc.sc_bus.use_polling--;
+ break;
+
+ case DVACT_RESUME:
+ sc->sc.sc_bus.use_polling++;
+#if 0
+ pxa2x0_clkman_config(CKEN_USBHC, 1);
+#endif
+ omohci_enable(sc);
+ ohci_power(why, &sc->sc);
+ sc->sc.sc_bus.use_polling--;
+ break;
+ }
+ return 0;
+}
+
+void
+omohci_enable(struct omohci_softc *sc)
+{
+#if 0
+ u_int32_t hr;
+
+ /* Full host reset */
+ hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
+ (hr & USBHC_HR_MASK) | USBHC_HR_FHR);
+
+ DELAY(USBHC_RST_WAIT);
+
+ hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
+ (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR));
+
+ /* Force system bus interface reset */
+ hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
+ (hr & USBHC_HR_MASK) | USBHC_HR_FSBIR);
+
+ while (bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR) & \
+ USBHC_HR_FSBIR)
+ DELAY(3);
+
+ /* Enable the ports (physically only one, only enable that one?) */
+ hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
+ (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSE));
+ hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
+ (hr & USBHC_HR_MASK) & ~(USBHC_HR_SSEP2));
+#endif
+}
+
+void
+omohci_disable(struct omohci_softc *sc)
+{
+#if 0
+ u_int32_t hr;
+
+ /* Full host reset */
+ hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
+ (hr & USBHC_HR_MASK) | USBHC_HR_FHR);
+
+ DELAY(USBHC_RST_WAIT);
+
+ hr = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USBHC_HR);
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USBHC_HR,
+ (hr & USBHC_HR_MASK) & ~(USBHC_HR_FHR));
+#endif
+}
--- /dev/null
+/* $OpenBSD: omusbtll.c,v 1.2 2013/11/06 19:03:07 syl Exp $ */
+/*
+ * Copyright (c) 2010 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/evcount.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/prcmvar.h>
+
+/* registers */
+#define USBTLL_REVISION 0x0000
+#define USBTLL_SYSCONFIG 0x0010
+#define USBTLL_SYSSTATUS 0x0014
+#define USBTLL_IRQSTATUS 0x0018
+#define USBTLL_IRQENABLE 0x001C
+#define USBTLL_SHARED_CONF 0x0030
+#define USBTLL_SHARED_CONF_USB_90D_DDR_EN (1<<6)
+#define USBTLL_SHARED_CONF_USB_180D_SDR_EN (1<<5)
+#define USBTLL_SHARED_CONF_USB_DIVRATIO_SH 2
+#define USBTLL_SHARED_CONF_FCLK_REQ (1<<1)
+#define USBTLL_SHARED_CONF_FCLK_IS_ON (1<<0)
+
+#define USBTLL_CHANNEL_CONF_(i) (0x0040 + (0x04 * (i)))
+#define USBTLL_CHANNEL_CONF_FSLSLINESTATE_SH 28
+#define USBTLL_CHANNEL_CONF_FSLSMODE_SH 24
+#define USBTLL_CHANNEL_CONF_TESTTXSE0 (1<<20)
+#define USBTLL_CHANNEL_CONF_TESTTXDAT (1<<19)
+#define USBTLL_CHANNEL_CONF_TESTTXEN (1<<18)
+#define USBTLL_CHANNEL_CONF_TESTEN (1<<17)
+#define USBTLL_CHANNEL_CONF_DRVVBUS (1<<16)
+#define USBTLL_CHANNEL_CONF_CHRGVBUS (1<<15)
+#define USBTLL_CHANNEL_CONF_ULPINOBITSTUFF (1<<11)
+#define USBTLL_CHANNEL_CONF_ULPIAUTOIDLE (1<<10)
+#define USBTLL_CHANNEL_CONF_UTMIAUTOIDLE (1<<9)
+#define USBTLL_CHANNEL_CONF_ULPIDDRMODE (1<<8)
+#define USBTLL_CHANNEL_CONF_LPIOUTCLKMODE (1<<7)
+#define USBTLL_CHANNEL_CONF_TLLFULLSPEED (1<<6)
+#define USBTLL_CHANNEL_CONF_TLLCONNECT (1<<5)
+#define USBTLL_CHANNEL_CONF_TLLATTACH (1<<4)
+#define USBTLL_CHANNEL_CONF_UTMIISADEV (1<<3)
+#define USBTLL_CHANNEL_CONF_CHANMODE_SH 1
+#define USBTLL_CHANNEL_CONF_CHANEN (1<<0)
+
+/*
+ULPI_VENDOR_ID_LO_(i) (0x0800 + (0x100 * (i)))
+ULPI_VENDOR_ID_HI_(i) (0x0801 + (0x100 * (i)))
+ULPI_PRODUCT_ID_LO_(i) (0x0802 + (0x100 * (i)))
+ULPI_PRODUCT_ID_HI_(i) (0x0803 + (0x100 * (i)))
+ULPI_FUNCTION_CTRL_(i) (0x0804 + (0x100 * (i)))
+ULPI_FUNCTION_CTRL_SET_(i) (0x0805 + (0x100 * (i)))
+ULPI_FUNCTION_CTRL_CLR_(i) (0x0806 + (0x100 * (i)))
+ULPI_INTERFACE_CTRL_(i) (0x0807 + (0x100 * (i)))
+ULPI_INTERFACE_CTRL_SET_(i) (0x0808 + (0x100 * (i)))
+ULPI_INTERFACE_CTRL_CLR_(i) (0x0809 + (0x100 * (i)))
+ULPI_OTG_CTRL_(i) (0x080A + (0x100 * (i)))
+ULPI_OTG_CTRL_SET_(i) (0x080B + (0x100 * (i)))
+ULPI_OTG_CTRL_CLR_(i) (0x080C + (0x100 * (i)))
+ULPI_USB_INT_EN_RISE_(i) (0x080D + (0x100 * (i)))
+ULPI_USB_INT_EN_RISE_SET_(i) (0x080E + (0x100 * (i)))
+ULPI_USB_INT_EN_RISE_CLR_(i) (0x080F + (0x100 * (i)))
+ULPI_USB_INT_EN_FALL_(i) (0x0810 + (0x100 * (i)))
+ULPI_USB_INT_EN_FALL_SET_(i) (0x0811 + (0x100 * (i)))
+ULPI_USB_INT_EN_FALL_CLR_(i) (0x0812 + (0x100 * (i)))
+ULPI_USB_INT_STATUS_(i) (0x0813 + (0x100 * (i)))
+ULPI_USB_INT_LATCH_(i) (0x0814 + (0x100 * (i)))
+*/
+
+struct omusbtll_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+void omusbtll_attach(struct device *parent, struct device *self, void *args);
+void omusbtll_init(uint32_t channel_mask);
+
+struct cfattach omusbtll_ca = {
+ sizeof (struct omusbtll_softc), NULL, omusbtll_attach
+};
+
+struct cfdriver omusbtll_cd = {
+ NULL, "omusbtll", DV_DULL
+};
+
+struct omusbtll_softc *omusbtll_sc;
+void
+omusbtll_attach(struct device *parent, struct device *self, void *args)
+{
+ struct omusbtll_softc *sc = (struct omusbtll_softc *) self;
+ struct armv7_attach_args *aa = args;
+ u_int32_t rev;
+
+ sc->sc_iot = aa->aa_iot;
+ if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_ioh)) {
+ printf("%s: bus_space_map failed!\n", __func__);
+ return;
+ }
+
+#if 0
+ prcm_enablemodule(PRCM_USBHOST1);
+ prcm_enablemodule(PRCM_USBHOST2);
+#endif
+ prcm_enablemodule(PRCM_USBTLL);
+
+ delay(10000);
+
+ //return;
+#if 1
+ rev = bus_space_read_1(sc->sc_iot, sc->sc_ioh, USBTLL_SYSCONFIG);
+
+ printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
+#endif
+
+ omusbtll_sc = sc;
+
+ omusbtll_init(0x3);
+}
+
+
+void omusbtll_init(uint32_t channel_mask)
+{
+ int i;
+ uint32_t val;
+ /* global reacharound */
+ struct omusbtll_softc *sc = omusbtll_sc;
+
+ for(i = 0; i < 3; i++) {
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+ USBTLL_CHANNEL_CONF_(i));
+ val &= ~(USBTLL_CHANNEL_CONF_ULPINOBITSTUFF |
+ USBTLL_CHANNEL_CONF_ULPIAUTOIDLE |
+ USBTLL_CHANNEL_CONF_ULPIDDRMODE);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+ USBTLL_CHANNEL_CONF_(i), val);
+ }
+
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, USBTLL_SHARED_CONF);
+ val |= (USBTLL_SHARED_CONF_USB_180D_SDR_EN |
+ (1 << USBTLL_SHARED_CONF_USB_DIVRATIO_SH) |
+ USBTLL_SHARED_CONF_FCLK_IS_ON);
+ val &= ~(USBTLL_SHARED_CONF_USB_90D_DDR_EN);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBTLL_SHARED_CONF, val);
+
+ for (i = 0; i < 3; i++) {
+ if (channel_mask & (1<<i)) {
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+ USBTLL_CHANNEL_CONF_(i));
+
+ val |= USBTLL_CHANNEL_CONF_CHANEN;
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+ USBTLL_CHANNEL_CONF_(i), val);
+ printf("usbtll enabling %d\n", i);
+ }
+ }
+}
--- /dev/null
+/* $OpenBSD: prcm.c,v 1.9 2014/05/08 21:17:01 miod Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray@gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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.
+ */
+
+/*
+ * Driver for the Power, Reset and Clock Management Module (PRCM).
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <arm/cpufunc.h>
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/prcmvar.h>
+
+#include <armv7/omap/am335x_prcmreg.h>
+#include <armv7/omap/omap3_prcmreg.h>
+#include <armv7/omap/omap4_prcmreg.h>
+
+#define PRCM_REVISION 0x0800
+#define PRCM_SYSCONFIG 0x0810
+
+uint32_t prcm_imask_mask[PRCM_REG_MAX];
+uint32_t prcm_fmask_mask[PRCM_REG_MAX];
+uint32_t prcm_imask_addr[PRCM_REG_MAX];
+uint32_t prcm_fmask_addr[PRCM_REG_MAX];
+
+#define SYS_CLK 13 /* SYS_CLK speed in MHz */
+
+struct prcm_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_prcm;
+ bus_space_handle_t sc_cm1;
+ bus_space_handle_t sc_cm2;
+ void (*sc_setup)(struct prcm_softc *sc);
+ void (*sc_enablemodule)(struct prcm_softc *sc, int mod);
+ void (*sc_setclock)(struct prcm_softc *sc,
+ int clock, int speed);
+ uint32_t cm1_avail;
+ uint32_t cm2_avail;
+};
+
+int prcm_match(struct device *, void *, void *);
+void prcm_attach(struct device *, struct device *, void *);
+int prcm_setup_dpll5(struct prcm_softc *);
+uint32_t prcm_v3_bit(int mod);
+uint32_t prcm_am335x_clkctrl(int mod);
+
+void prcm_am335x_enablemodule(struct prcm_softc *, int);
+void prcm_am335x_setclock(struct prcm_softc *, int, int);
+
+void prcm_v3_setup(struct prcm_softc *);
+void prcm_v3_enablemodule(struct prcm_softc *, int);
+void prcm_v3_setclock(struct prcm_softc *, int, int);
+
+void prcm_v4_enablemodule(struct prcm_softc *, int);
+int prcm_v4_hsusbhost_activate(int);
+int prcm_v4_hsusbhost_set_source(int, int);
+
+struct cfattach prcm_ca = {
+ sizeof (struct prcm_softc), NULL, prcm_attach
+};
+
+struct cfdriver prcm_cd = {
+ NULL, "prcm", DV_DULL
+};
+
+void
+prcm_attach(struct device *parent, struct device *self, void *args)
+{
+ struct armv7_attach_args *aa = args;
+ struct prcm_softc *sc = (struct prcm_softc *) self;
+ u_int32_t reg;
+
+ sc->sc_iot = aa->aa_iot;
+
+ switch (board_id) {
+ case BOARD_ID_AM335X_BEAGLEBONE:
+ sc->sc_setup = NULL;
+ sc->sc_enablemodule = prcm_am335x_enablemodule;
+ sc->sc_setclock = prcm_am335x_setclock;
+ break;
+ case BOARD_ID_OMAP3_BEAGLE:
+ case BOARD_ID_OMAP3_OVERO:
+ sc->sc_setup = prcm_v3_setup;
+ sc->sc_enablemodule = prcm_v3_enablemodule;
+ sc->sc_setclock = prcm_v3_setclock;
+ break;
+ case BOARD_ID_OMAP4_PANDA:
+ sc->sc_setup = NULL;
+ sc->sc_enablemodule = prcm_v4_enablemodule;
+ sc->sc_setclock = NULL;
+ sc->cm1_avail = 1;
+ sc->cm2_avail = 1;
+ break;
+ }
+
+ if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_prcm))
+ panic("prcm_attach: bus_space_map failed!");
+
+ if (sc->cm1_avail &&
+ bus_space_map(sc->sc_iot, aa->aa_dev->mem[1].addr,
+ aa->aa_dev->mem[1].size, 0, &sc->sc_cm1))
+ panic("prcm_attach: bus_space_map failed!");
+
+ if (sc->cm2_avail &&
+ bus_space_map(sc->sc_iot, aa->aa_dev->mem[2].addr,
+ aa->aa_dev->mem[2].size, 0, &sc->sc_cm2))
+ panic("prcm_attach: bus_space_map failed!");
+
+ reg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, PRCM_REVISION);
+ printf(" rev %d.%d\n", reg >> 4 & 0xf, reg & 0xf);
+
+ if (sc->sc_setup != NULL)
+ sc->sc_setup(sc);
+}
+
+void
+prcm_v3_setup(struct prcm_softc *sc)
+{
+ /* Setup the 120MHZ DPLL5 clock, to be used by USB. */
+ prcm_setup_dpll5(sc);
+
+ prcm_fmask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FMASK;
+ prcm_imask_mask[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IMASK;
+ prcm_fmask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_FADDR;
+ prcm_imask_addr[PRCM_REG_CORE_CLK1] = PRCM_REG_CORE_CLK1_IADDR;
+
+ prcm_fmask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FMASK;
+ prcm_imask_mask[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IMASK;
+ prcm_fmask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_FADDR;
+ prcm_imask_addr[PRCM_REG_CORE_CLK2] = PRCM_REG_CORE_CLK2_IADDR;
+
+ prcm_fmask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FMASK;
+ prcm_imask_mask[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IMASK;
+ prcm_fmask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_FADDR;
+ prcm_imask_addr[PRCM_REG_CORE_CLK3] = PRCM_REG_CORE_CLK3_IADDR;
+
+ prcm_fmask_mask[PRCM_REG_WKUP] = PRCM_REG_WKUP_FMASK;
+ prcm_imask_mask[PRCM_REG_WKUP] = PRCM_REG_WKUP_IMASK;
+ prcm_fmask_addr[PRCM_REG_WKUP] = PRCM_REG_WKUP_FADDR;
+ prcm_imask_addr[PRCM_REG_WKUP] = PRCM_REG_WKUP_IADDR;
+
+ prcm_fmask_mask[PRCM_REG_PER] = PRCM_REG_PER_FMASK;
+ prcm_imask_mask[PRCM_REG_PER] = PRCM_REG_PER_IMASK;
+ prcm_fmask_addr[PRCM_REG_PER] = PRCM_REG_PER_FADDR;
+ prcm_imask_addr[PRCM_REG_PER] = PRCM_REG_PER_IADDR;
+
+ prcm_fmask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FMASK;
+ prcm_imask_mask[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IMASK;
+ prcm_fmask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_FADDR;
+ prcm_imask_addr[PRCM_REG_USBHOST] = PRCM_REG_USBHOST_IADDR;
+}
+
+void
+prcm_setclock(int clock, int speed)
+{
+ struct prcm_softc *sc = prcm_cd.cd_devs[0];
+
+ if (!sc->sc_setclock)
+ panic("%s: not initialised!", __func__);
+
+ sc->sc_setclock(sc, clock, speed);
+}
+
+void
+prcm_am335x_setclock(struct prcm_softc *sc, int clock, int speed)
+{
+ u_int32_t oreg, reg, mask;
+
+ /* set CLKSEL register */
+ if (clock == 1) {
+ oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm,
+ PRCM_AM335X_CLKSEL_TIMER2_CLK);
+ mask = 3;
+ reg = oreg & ~mask;
+ reg |=0x02;
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm,
+ PRCM_AM335X_CLKSEL_TIMER2_CLK, reg);
+ } else if (clock == 2) {
+ oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm,
+ PRCM_AM335X_CLKSEL_TIMER3_CLK);
+ mask = 3;
+ reg = oreg & ~mask;
+ reg |=0x02;
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm,
+ PRCM_AM335X_CLKSEL_TIMER3_CLK, reg);
+ }
+}
+
+void
+prcm_v3_setclock(struct prcm_softc *sc, int clock, int speed)
+{
+ u_int32_t oreg, reg, mask;
+
+ if (clock == 1) {
+ oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP);
+ mask = 1;
+ reg = (oreg &~mask) | (speed & mask);
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_WKUP, reg);
+ } else if (clock >= 2 && clock <= 9) {
+ int shift = (clock-2);
+ oreg = bus_space_read_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER);
+ mask = 1 << (shift);
+ reg = (oreg & ~mask) | ( (speed << shift) & mask);
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL_PER, reg);
+ } else
+ panic("%s: invalid clock %d", __func__, clock);
+}
+
+uint32_t
+prcm_v3_bit(int mod)
+{
+ switch(mod) {
+ case PRCM_MMC0:
+ return PRCM_CLK_EN_MMC1;
+ case PRCM_MMC1:
+ return PRCM_CLK_EN_MMC2;
+ case PRCM_MMC2:
+ return PRCM_CLK_EN_MMC3;
+ case PRCM_USB:
+ return PRCM_CLK_EN_USB;
+ case PRCM_GPIO0:
+ return PRCM_CLK_EN_GPIO1;
+ case PRCM_GPIO1:
+ return PRCM_CLK_EN_GPIO2;
+ case PRCM_GPIO2:
+ return PRCM_CLK_EN_GPIO3;
+ case PRCM_GPIO3:
+ return PRCM_CLK_EN_GPIO4;
+ case PRCM_GPIO4:
+ return PRCM_CLK_EN_GPIO5;
+ case PRCM_GPIO5:
+ return PRCM_CLK_EN_GPIO6;
+ default:
+ panic("%s: module not found\n", __func__);
+ }
+}
+
+uint32_t
+prcm_am335x_clkctrl(int mod)
+{
+ switch(mod) {
+ case PRCM_TIMER2:
+ return PRCM_AM335X_TIMER2_CLKCTRL;
+ case PRCM_TIMER3:
+ return PRCM_AM335X_TIMER3_CLKCTRL;
+ case PRCM_MMC0:
+ return PRCM_AM335X_MMC0_CLKCTRL;
+ case PRCM_MMC1:
+ return PRCM_AM335X_MMC1_CLKCTRL;
+ case PRCM_MMC2:
+ return PRCM_AM335X_MMC2_CLKCTRL;
+ case PRCM_USB:
+ return PRCM_AM335X_USB0_CLKCTRL;
+ case PRCM_GPIO0:
+ return PRCM_AM335X_GPIO0_CLKCTRL;
+ case PRCM_GPIO1:
+ return PRCM_AM335X_GPIO1_CLKCTRL;
+ case PRCM_GPIO2:
+ return PRCM_AM335X_GPIO2_CLKCTRL;
+ case PRCM_GPIO3:
+ return PRCM_AM335X_GPIO3_CLKCTRL;
+ case PRCM_TPCC:
+ return PRCM_AM335X_TPCC_CLKCTRL;
+ case PRCM_TPTC0:
+ return PRCM_AM335X_TPTC0_CLKCTRL;
+ case PRCM_TPTC1:
+ return PRCM_AM335X_TPTC1_CLKCTRL;
+ case PRCM_TPTC2:
+ return PRCM_AM335X_TPTC2_CLKCTRL;
+ case PRCM_I2C0:
+ return PRCM_AM335X_I2C0_CLKCTRL;
+ case PRCM_I2C1:
+ return PRCM_AM335X_I2C1_CLKCTRL;
+ case PRCM_I2C2:
+ return PRCM_AM335X_I2C2_CLKCTRL;
+ default:
+ panic("%s: module not found\n", __func__);
+ }
+}
+
+void
+prcm_enablemodule(int mod)
+{
+ struct prcm_softc *sc = prcm_cd.cd_devs[0];
+
+ if (!sc->sc_enablemodule)
+ panic("%s: not initialised!", __func__);
+
+ sc->sc_enablemodule(sc, mod);
+}
+
+void
+prcm_am335x_enablemodule(struct prcm_softc *sc, int mod)
+{
+ uint32_t clkctrl;
+ int reg;
+
+ /*set enable bits in CLKCTRL register */
+ reg = prcm_am335x_clkctrl(mod);
+ clkctrl = bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg);
+ clkctrl &=~AM335X_CLKCTRL_MODULEMODE_MASK;
+ clkctrl |= AM335X_CLKCTRL_MODULEMODE_ENABLE;
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm, reg, clkctrl);
+
+ /* wait until module is enabled */
+ while (bus_space_read_4(sc->sc_iot, sc->sc_prcm, reg) & 0x30000)
+ ;
+}
+
+void
+prcm_v3_enablemodule(struct prcm_softc *sc, int mod)
+{
+ uint32_t bit;
+ uint32_t fclk, iclk, fmask, imask, mbit;
+ int freg, ireg, reg;
+
+ bit = prcm_v3_bit(mod);
+ reg = bit >> 5;
+
+ freg = prcm_fmask_addr[reg];
+ ireg = prcm_imask_addr[reg];
+ fmask = prcm_fmask_mask[reg];
+ imask = prcm_imask_mask[reg];
+
+ mbit = 1 << (bit & 0x1f);
+ if (fmask & mbit) { /* dont access the register if bit isn't present */
+ fclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, freg);
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm, freg, fclk | mbit);
+ }
+ if (imask & mbit) { /* dont access the register if bit isn't present */
+ iclk = bus_space_read_4(sc->sc_iot, sc->sc_prcm, ireg);
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm, ireg, iclk | mbit);
+ }
+ printf("\n");
+}
+
+void
+prcm_v4_enablemodule(struct prcm_softc *sc, int mod)
+{
+ switch (mod) {
+ case PRCM_MMC0:
+ break;
+ case PRCM_USBP1_PHY:
+ case PRCM_USBP2_PHY:
+ prcm_v4_hsusbhost_set_source(mod, 0);
+ case PRCM_USB:
+ case PRCM_USBTLL:
+ case PRCM_USBP1_UTMI:
+ case PRCM_USBP1_HSIC:
+ case PRCM_USBP2_UTMI:
+ case PRCM_USBP2_HSIC:
+ prcm_v4_hsusbhost_activate(mod);
+ return;
+ case PRCM_GPIO0:
+ case PRCM_GPIO1:
+ case PRCM_GPIO2:
+ case PRCM_GPIO3:
+ case PRCM_GPIO4:
+ case PRCM_GPIO5:
+ /* XXX */
+ break;
+ default:
+ panic("%s: module not found\n", __func__);
+ }
+}
+
+int
+prcm_v4_hsusbhost_activate(int type)
+{
+ struct prcm_softc *sc = prcm_cd.cd_devs[0];
+ uint32_t i;
+ uint32_t clksel_reg_off;
+ uint32_t clksel, oclksel;
+
+ switch (type) {
+ case PRCM_USB:
+ case PRCM_USBP1_PHY:
+ case PRCM_USBP2_PHY:
+ /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
+ clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58;
+ clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off);
+ oclksel = clksel;
+ /* Enable the module and also enable the optional func clocks */
+ if (type == PRCM_USB) {
+ clksel &= ~O4_CLKCTRL_MODULEMODE_MASK;
+ clksel |= /*O4_CLKCTRL_MODULEMODE_ENABLE*/2;
+
+ clksel |= (0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */
+ }
+
+ break;
+
+ default:
+ panic("%s: invalid type %d", __func__, type);
+ return (EINVAL);
+ }
+ bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel);
+
+ /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */
+ for (i = 0; i < O4_MAX_MODULE_ENABLE_WAIT; i++) {
+ clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off);
+ if ((clksel & O4_CLKCTRL_IDLEST_MASK) == O4_CLKCTRL_IDLEST_ENABLED)
+ break;
+ }
+
+ /* Check the enabled state */
+ if ((clksel & O4_CLKCTRL_IDLEST_MASK) != O4_CLKCTRL_IDLEST_ENABLED) {
+ printf("Error: HERE failed to enable module with clock %d\n", type);
+ printf("Error: 0x%08x => 0x%08x\n", clksel_reg_off, clksel);
+ return (ETIMEDOUT);
+ }
+
+ return (0);
+}
+
+int
+prcm_v4_hsusbhost_set_source(int clk, int clksrc)
+{
+ struct prcm_softc *sc = prcm_cd.cd_devs[0];
+ uint32_t clksel_reg_off;
+ uint32_t clksel;
+ unsigned int bit;
+
+ if (clk == PRCM_USBP1_PHY)
+ bit = 24;
+ else if (clk != PRCM_USBP2_PHY)
+ bit = 25;
+ else
+ return (-EINVAL);
+
+ /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
+ clksel_reg_off = O4_L3INIT_CM2_OFFSET + 0x58;
+ clksel = bus_space_read_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off);
+
+ /* XXX: Set the clock source to either external or internal */
+ if (clksrc == 0)
+ clksel |= (0x1 << bit);
+ else
+ clksel &= ~(0x1 << bit);
+
+ bus_space_write_4(sc->sc_iot, sc->sc_cm2, clksel_reg_off, clksel);
+
+ return (0);
+}
+
+/*
+ * OMAP35xx Power, Reset, and Clock Management Reference Guide
+ * (sprufa5.pdf) and AM/DM37x Multimedia Device Technical Reference
+ * Manual (sprugn4h.pdf) note that DPLL5 provides a 120MHz clock for
+ * peripheral domain modules (page 107 and page 302).
+ * The reference clock for DPLL5 is DPLL5_ALWON_FCLK which is
+ * SYS_CLK, running at 13MHz.
+ */
+int
+prcm_setup_dpll5(struct prcm_softc *sc)
+{
+ uint32_t val;
+
+ /*
+ * We need to set the multiplier and divider values for PLL.
+ * To end up with 120MHz we take SYS_CLK, divide by it and multiply
+ * with 120 (sprugn4h.pdf, 13.4.11.4.1 SSC Configuration)
+ */
+ val = ((120 & 0x7ff) << 8) | ((SYS_CLK - 1) & 0x7f);
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL4_PLL, val);
+
+ /* Clock divider from the PLL to the 120MHz clock. */
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKSEL5_PLL, val);
+
+ /*
+ * spruf98o.pdf, page 2319:
+ * PERIPH2_DPLL_FREQSEL is 0x7 1.75MHz to 2.1MHz
+ * EN_PERIPH2_DPLL is 0x7
+ */
+ val = (7 << 4) | (7 << 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_CLKEN2_PLL, val);
+
+ /* Disable the interconnect clock auto-idle. */
+ bus_space_write_4(sc->sc_iot, sc->sc_prcm, CM_AUTOIDLE2_PLL, 0x0);
+
+ /* Wait until DPLL5 is locked and there's clock activity. */
+ while ((val = bus_space_read_4(sc->sc_iot, sc->sc_prcm,
+ CM_IDLEST_CKGEN) & 0x01) == 0x00) {
+#ifdef DIAGNOSTIC
+ printf("CM_IDLEST_PLL = 0x%08x\n", val);
+#endif
+ }
+
+ return 0;
+}
--- /dev/null
+/* $OpenBSD: prcmvar.h,v 1.5 2014/03/18 07:34:17 syl Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+void prcm_setclock(int clock, int speed);
+void prcm_enablemodule(int mod);
+void prcm_disablemodule(int mod);
+
+#define PRCM_CLK_SPEED_32 0
+#define PRCM_CLK_SPEED_SYS 1
+
+enum PRCM_MODULES {
+ PRCM_TIMER0,
+ PRCM_TIMER1,
+ PRCM_TIMER2,
+ PRCM_TIMER3,
+ PRCM_GPIO0,
+ PRCM_GPIO1,
+ PRCM_GPIO2,
+ PRCM_GPIO3,
+ PRCM_GPIO4,
+ PRCM_GPIO5,
+ PRCM_TPCC,
+ PRCM_TPTC0,
+ PRCM_TPTC1,
+ PRCM_TPTC2,
+ PRCM_MMC0,
+ PRCM_MMC1,
+ PRCM_MMC2,
+ PRCM_USB,
+ PRCM_USBTLL,
+ PRCM_USBP1_PHY,
+ PRCM_USBP1_UTMI,
+ PRCM_USBP1_HSIC,
+ PRCM_USBP2_PHY,
+ PRCM_USBP2_UTMI,
+ PRCM_USBP2_HSIC,
+ PRCM_I2C0,
+ PRCM_I2C1,
+ PRCM_I2C2,
+};
+
+#define PRCM_REG_MAX 6
+/* need interface for CM_AUTOIDLE */
--- /dev/null
+/* $OpenBSD: sitara_cm.c,v 1.2 2013/11/06 19:03:07 syl Exp $ */
+/* $NetBSD: sitara_cm.c,v 1.1 2013/04/17 14:31:02 bouyer Exp $ */
+/*
+ * Copyright (c) 2010
+ * Ben Gray <ben.r.gray@gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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.
+ */
+
+/*
+ * SCM - System Control Module
+ *
+ * Hopefully in the end this module will contain a bunch of utility functions
+ * for configuring and querying the general system control registers, but for
+ * now it only does pin(pad) multiplexing.
+ *
+ * This is different from the GPIO module in that it is used to configure the
+ * pins between modules not just GPIO input/output.
+ *
+ * This file contains the generic top level driver, however it relies on chip
+ * specific settings and therefore expects an array of sitara_cm_padconf structs
+ * call ti_padconf_devmap to be located somewhere in the kernel.
+ *
+ */
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <machine/bus.h>
+
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/sitara_cm.h>
+#include <armv7/omap/sitara_cmreg.h>
+
+void sitara_cm_attach(struct device *parent, struct device *self, void *aux);
+
+struct sitara_cm_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+struct cfattach sitaracm_ca = {
+ sizeof (struct sitara_cm_softc), NULL, sitara_cm_attach
+};
+
+struct cfdriver sitaracm_cd = {
+ NULL, "sitaracm", DV_DULL
+};
+
+static struct sitara_cm_softc *sitara_cm_sc = NULL;
+
+#define sitara_cm_read_2(sc, reg) \
+ bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (reg))
+#define sitara_cm_write_2(sc, reg, val) \
+ bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+#define sitara_cm_read_4(sc, reg) \
+ bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
+#define sitara_cm_write_4(sc, reg, val) \
+ bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+
+
+/**
+ * ti_padconf_devmap - Array of pins, should be defined one per SoC
+ *
+ * This array is typically defined in one of the targeted *_scm_pinumx.c
+ * files and is specific to the given SoC platform. Each entry in the array
+ * corresponds to an individual pin.
+ */
+extern const struct sitara_cm_device sitara_cm_dev;
+
+
+/**
+ * sitara_cm_padconf_from_name - searches the list of pads and returns entry
+ * with matching ball name.
+ * @ballname: the name of the ball
+ *
+ * RETURNS:
+ * A pointer to the matching padconf or NULL if the ball wasn't found.
+ */
+static const struct sitara_cm_padconf*
+sitara_cm_padconf_from_name(const char *ballname)
+{
+ const struct sitara_cm_padconf *padconf;
+
+ padconf = sitara_cm_dev.padconf;
+ while (padconf->ballname != NULL) {
+ if (strcmp(ballname, padconf->ballname) == 0)
+ return(padconf);
+ padconf++;
+ }
+
+ return (NULL);
+}
+
+/**
+ * sitara_cm_padconf_set_internal - sets the muxmode and state for a pad/pin
+ * @padconf: pointer to the pad structure
+ * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
+ * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or already in use.
+ */
+static int
+sitara_cm_padconf_set_internal(struct sitara_cm_softc *sc,
+ const struct sitara_cm_padconf *padconf,
+ const char *muxmode, unsigned int state)
+{
+ unsigned int mode;
+ uint16_t reg_val;
+
+ /* populate the new value for the PADCONF register */
+ reg_val = (uint16_t)(state & sitara_cm_dev.padconf_sate_mask);
+
+ /* find the new mode requested */
+ for (mode = 0; mode < 8; mode++) {
+ if ((padconf->muxmodes[mode] != NULL) &&
+ (strcmp(padconf->muxmodes[mode], muxmode) == 0)) {
+ break;
+ }
+ }
+
+ /* couldn't find the mux mode */
+ if (mode >= 8) {
+ printf("%s: Invalid mux mode \"%s\"\n", __func__, muxmode);
+ return (EINVAL);
+ }
+
+ /* set the mux mode */
+ reg_val |= (uint16_t)(mode & sitara_cm_dev.padconf_muxmode_mask);
+
+ /* write the register value (16-bit writes) */
+ sitara_cm_write_2(sc, padconf->reg_off, reg_val);
+
+ return (0);
+}
+
+/**
+ * sitara_cm_padconf_set - sets the muxmode and state for a pad/pin
+ * @padname: the name of the pad, i.e. "c12"
+ * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
+ * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or already in use.
+ */
+int
+sitara_cm_padconf_set(const char *padname, const char *muxmode, unsigned int state)
+{
+ const struct sitara_cm_padconf *padconf;
+
+ if (!sitara_cm_sc)
+ return (ENXIO);
+
+ /* find the pin in the devmap */
+ padconf = sitara_cm_padconf_from_name(padname);
+ if (padconf == NULL)
+ return (EINVAL);
+
+ return (
+ sitara_cm_padconf_set_internal(sitara_cm_sc, padconf, muxmode, state)
+ );
+}
+
+/**
+ * sitara_cm_padconf_get - gets the muxmode and state for a pad/pin
+ * @padname: the name of the pad, i.e. "c12"
+ * @muxmode: upon return will contain the name of the muxmode of the pin
+ * @state: upon return will contain the state of the pad/pin
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or already in use.
+ */
+int
+sitara_cm_padconf_get(const char *padname, const char **muxmode,
+ unsigned int *state)
+{
+ const struct sitara_cm_padconf *padconf;
+ uint16_t reg_val;
+
+ if (!sitara_cm_sc)
+ return (ENXIO);
+
+ /* find the pin in the devmap */
+ padconf = sitara_cm_padconf_from_name(padname);
+ if (padconf == NULL)
+ return (EINVAL);
+
+ /* read the register value (16-bit reads) */
+ reg_val = sitara_cm_read_2(sitara_cm_sc, padconf->reg_off);
+
+ /* save the state */
+ if (state)
+ *state = (reg_val & sitara_cm_dev.padconf_sate_mask);
+
+ /* save the mode */
+ if (muxmode) {
+ *muxmode = padconf->muxmodes[
+ (reg_val & sitara_cm_dev.padconf_muxmode_mask)
+ ];
+ }
+
+ return (0);
+}
+
+/**
+ * sitara_cm_padconf_set_gpiomode - converts a pad to GPIO mode.
+ * @gpio: the GPIO pin number (0-195)
+ * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
+ *
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or already in use.
+ */
+int
+sitara_cm_padconf_set_gpiomode(uint32_t gpio, unsigned int state)
+{
+ const struct sitara_cm_padconf *padconf;
+ uint16_t reg_val;
+
+ if (!sitara_cm_sc)
+ return (ENXIO);
+
+ /* find the gpio pin in the padconf array */
+ padconf = sitara_cm_dev.padconf;
+ while (padconf->ballname != NULL) {
+ if (padconf->gpio_pin == gpio)
+ break;
+ padconf++;
+ }
+ if (padconf->ballname == NULL)
+ return (EINVAL);
+
+ /* populate the new value for the PADCONF register */
+ reg_val = (uint16_t)(state & sitara_cm_dev.padconf_sate_mask);
+
+ /* set the mux mode */
+ reg_val |=
+ (uint16_t)(padconf->gpio_mode & sitara_cm_dev.padconf_muxmode_mask);
+
+ /* write the register value (16-bit writes) */
+ sitara_cm_write_2(sitara_cm_sc, padconf->reg_off, reg_val);
+
+ return (0);
+}
+
+/**
+ * sitara_cm_padconf_get_gpiomode - gets the current GPIO mode of the pin
+ * @gpio: the GPIO pin number (0-195)
+ * @state: upon return will contain the state
+ *
+ *
+ *
+ * LOCKING:
+ * Internally locks it's own context.
+ *
+ * RETURNS:
+ * 0 on success.
+ * EINVAL if pin requested is outside valid range or not configured as GPIO.
+ */
+int
+sitara_cm_padconf_get_gpiomode(uint32_t gpio, unsigned int *state)
+{
+ const struct sitara_cm_padconf *padconf;
+ uint16_t reg_val;
+
+ if (!sitara_cm_sc)
+ return (ENXIO);
+
+ /* find the gpio pin in the padconf array */
+ padconf = sitara_cm_dev.padconf;
+ while (padconf->ballname != NULL) {
+ if (padconf->gpio_pin == gpio)
+ break;
+ padconf++;
+ }
+ if (padconf->ballname == NULL)
+ return (EINVAL);
+
+ /* read the current register settings */
+ reg_val = sitara_cm_read_2(sitara_cm_sc, padconf->reg_off);
+
+ /*
+ * check to make sure the pins is configured as GPIO in the
+ * first state
+ */
+ if ((reg_val & sitara_cm_dev.padconf_muxmode_mask) !=
+ padconf->gpio_mode)
+ return (EINVAL);
+
+ /*
+ * read and store the reset of the state,
+ * i.e. pull-up, pull-down, etc
+ */
+ if (state)
+ *state = (reg_val & sitara_cm_dev.padconf_sate_mask);
+
+ return (0);
+}
+
+
+int
+sitara_cm_reg_read_4(uint32_t reg, uint32_t *val)
+{
+ if (!sitara_cm_sc)
+ return (ENXIO);
+
+ *val = sitara_cm_read_4(sitara_cm_sc, reg);
+ return (0);
+}
+
+int
+sitara_cm_reg_write_4(uint32_t reg, uint32_t val)
+{
+ if (!sitara_cm_sc)
+ return (ENXIO);
+
+ sitara_cm_write_4(sitara_cm_sc, reg, val);
+ return (0);
+}
+
+void
+sitara_cm_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct sitara_cm_softc *sc = (struct sitara_cm_softc *)self;
+ struct armv7_attach_args *aa = aux;
+ uint32_t rev;
+
+ if (sitara_cm_sc)
+ panic("sitara_cm_attach: already attached");
+
+ sc->sc_iot = aa->aa_iot;
+
+ if (bus_space_map(aa->aa_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_ioh) != 0)
+ panic("%s: bus_space_map failed!\n", __func__);
+
+ sitara_cm_sc = sc;
+
+ if (sitara_cm_reg_read_4(OMAP2SCM_REVISION, &rev) != 0)
+ panic("sitara_cm_attach: read revision");
+ printf(": control module, rev %d.%d\n",
+ SCM_REVISION_MAJOR(rev), SCM_REVISION_MINOR(rev));
+}
--- /dev/null
+/* $OpenBSD: sitara_cm.h,v 1.1 2013/09/04 14:38:32 patrick Exp $ */
+/* $NetBSD: sitara_cm.h,v 1.1 2013/04/17 14:31:02 bouyer Exp $ */
+/*
+ * Copyright (c) 2010
+ * Ben Gray <ben.r.gray@gmail.com>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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.
+ *
+ */
+
+
+/**
+ * Functions to configure the PIN multiplexing on the chip.
+ *
+ * This is different from the GPIO module in that it is used to configure the
+ * pins between modules not just GPIO input output.
+ *
+ */
+#ifndef _OMAP_SCM_H_
+#define _OMAP_SCM_H_
+
+struct sitara_cm_padconf {
+ uint16_t reg_off;
+ uint16_t gpio_pin;
+ uint16_t gpio_mode;
+ const char *ballname;
+ const char *muxmodes[8];
+};
+
+struct sitara_cm_padstate {
+ const char *state;
+ uint16_t reg;
+};
+
+struct sitara_cm_device {
+ uint16_t padconf_muxmode_mask;
+ uint16_t padconf_sate_mask;
+ struct sitara_cm_padstate *padstate;
+ struct sitara_cm_padconf *padconf;
+};
+
+int sitara_cm_padconf_set(const char *padname, const char *muxmode,
+ unsigned int state);
+int sitara_cm_padconf_get(const char *padname, const char **muxmode,
+ unsigned int *state);
+int sitara_cm_padconf_set_gpiomode(uint32_t gpio, unsigned int state);
+int sitara_cm_padconf_get_gpiomode(uint32_t gpio, unsigned int *state);
+int sitara_cm_padconf_set_gpioflags(uint32_t gpio, uint32_t flags);
+void sitara_cm_padconf_get_gpioflags(uint32_t gpio, uint32_t *flags);
+int sitara_cm_reg_read_4(uint32_t reg, uint32_t *val);
+int sitara_cm_reg_write_4(uint32_t reg, uint32_t val);
+
+#endif /* _OMAP_SCM_H_ */
--- /dev/null
+/* $OpenBSD: sitara_cmreg.h,v 1.1 2013/09/04 14:38:32 patrick Exp $ */
+/* $NetBSD: sitara_cmreg.h,v 1.1 2013/04/17 15:04:39 bouyer Exp $ */
+
+/*
+ * Copyright (c) 2013 Manuel Bouyer. 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 ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* register definitions for the Control module found in the
+ * Texas Instrument AM335x SOC
+ */
+
+#ifndef _OMAP2SCMREG_H
+#define _OMAP2SCMREG_H
+
+#define OMAP2SCM_REVISION 0x0000
+#define SCM_REVISION_SCHEME(x) (((x) & 0xc0000000) >> 30)
+#define SCM_REVISION_FUNC(x) (((x) & 0x0fff0000) >> 16)
+#define SCM_REVISION_RTL(x) (((x) & 0x0000f800) >> 11)
+#define SCM_REVISION_MAJOR(x) (((x) & 0x00000700) >> 8)
+#define SCM_REVISION_CUSTOM(x) (((x) & 0x000000c0) >> 6)
+#define SCM_REVISION_MINOR(x) (((x) & 0x0000001f) >> 0)
+
+#define OMAP2SCM_MAC_ID0_LO 0x630
+#define OMAP2SCM_MAC_ID0_HI 0x634
+
+#endif /* _OMAP2SCMREG_H */
--- /dev/null
+/* $OpenBSD: ti_iic.c,v 1.2 2014/03/18 14:23:52 rapha Exp $ */
+/* $NetBSD: ti_iic.c,v 1.4 2013/04/25 13:04:27 rkujawa Exp $ */
+
+/*
+ * Copyright (c) 2013 Manuel Bouyer. 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 ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2012 Jared D. McNeill <jmcneill@invisible.ca>
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/rwlock.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/i2c/i2cvar.h>
+
+#include <armv7/armv7/armv7var.h>
+#include <armv7/omap/prcmvar.h>
+#include <armv7/omap/sitara_cm.h>
+#include <armv7/omap/sitara_cmreg.h>
+#include <armv7/omap/ti_iicreg.h>
+
+#ifndef AM335X_I2C_SLAVE_ADDR
+#define AM335X_I2C_SLAVE_ADDR 0x01
+#endif
+
+#ifdef I2CDEBUG
+#define DPRINTF(args) printf args
+#else
+#define DPRINTF(args)
+#endif
+
+/* operation in progress */
+typedef enum {
+ TI_I2CREAD,
+ TI_I2CWRITE,
+ TI_I2CDONE,
+ TI_I2CERROR
+} ti_i2cop_t;
+
+struct ti_iic_softc {
+ struct device sc_dev;
+ struct i2c_controller sc_ic;
+ struct rwlock sc_buslock;
+ struct device *sc_i2cdev;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ void *sc_ih;
+ ti_i2cop_t sc_op;
+ int sc_buflen;
+ int sc_bufidx;
+ char *sc_buf;
+
+ int sc_rxthres;
+ int sc_txthres;
+};
+
+
+#define I2C_READ_REG(sc, reg) \
+ bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (reg))
+#define I2C_READ_DATA(sc) \
+ bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, AM335X_I2C_DATA);
+#define I2C_WRITE_REG(sc, reg, val) \
+ bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+#define I2C_WRITE_DATA(sc, val) \
+ bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, AM335X_I2C_DATA, (val))
+
+#define DEVNAME(sc) ((sc)->sc_dev.dv_xname)
+
+static void ti_iic_attach(struct device *, struct device *, void *);
+static int ti_iic_intr(void *);
+
+static int ti_iic_acquire_bus(void *, int);
+static void ti_iic_release_bus(void *, int);
+static int ti_iic_exec(void *, i2c_op_t, i2c_addr_t, const void *,
+ size_t, void *, size_t, int);
+
+static int ti_iic_reset(struct ti_iic_softc *);
+static int ti_iic_op(struct ti_iic_softc *, i2c_addr_t, ti_i2cop_t,
+ uint8_t *, size_t, int);
+static void ti_iic_handle_intr(struct ti_iic_softc *, uint32_t);
+static void ti_iic_do_read(struct ti_iic_softc *, uint32_t);
+static void ti_iic_do_write(struct ti_iic_softc *, uint32_t);
+
+static int ti_iic_wait(struct ti_iic_softc *, uint16_t, uint16_t, int);
+static uint32_t ti_iic_stat(struct ti_iic_softc *, uint32_t);
+static int ti_iic_flush(struct ti_iic_softc *);
+
+struct cfattach tiiic_ca = {
+ sizeof (struct ti_iic_softc), NULL, ti_iic_attach
+};
+
+struct cfdriver tiiic_cd = {
+ NULL, "tiiic", DV_DULL
+};
+
+static void
+ti_iic_attach(struct device *parent, struct device *self, void *args)
+{
+ struct ti_iic_softc *sc = (struct ti_iic_softc *)self;
+ struct armv7_attach_args *aa = args;
+ struct i2cbus_attach_args iba;
+ uint16_t rev;
+ const char *mode;
+ u_int state;
+ char buf[20];
+ char *pin;
+ /* BBB specific pin names */
+ char *pins[6] = {"I2C0_SDA", "I2C0_SCL",
+ "SPIO_D1", "SPI0_CS0",
+ "UART1_CTSn", "UART1_RTSn"};
+
+ sc->sc_iot = aa->aa_iot;
+ rw_init(&sc->sc_buslock, "tiiilk");
+
+ sc->sc_rxthres = sc->sc_txthres = 4;
+
+ if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
+ aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
+ panic("%s: bus_space_map failed!");
+
+ sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_NET,
+ ti_iic_intr, sc, DEVNAME(sc));
+
+ prcm_enablemodule(PRCM_I2C0 + aa->aa_dev->unit);
+
+ if (board_id == BOARD_ID_AM335X_BEAGLEBONE) {
+ pin = pins[aa->aa_dev->unit * 2];
+ snprintf(buf, sizeof buf, "I2C%d_SDA", aa->aa_dev->unit);
+ if (sitara_cm_padconf_set(pin, buf,
+ (0x01 << 4) | (0x01 << 5) | (0x01 << 6)) != 0) {
+ printf(": can't switch %s pad\n", buf);
+ return;
+ }
+ if (sitara_cm_padconf_get(pin, &mode, &state) == 0) {
+ printf(": %s state %d ", mode, state);
+ }
+
+ pin = pins[aa->aa_dev->unit * 2 + 1];
+ snprintf(buf, sizeof buf, "I2C%d_SCL", aa->aa_dev->unit);
+ if (sitara_cm_padconf_set(pin, buf,
+ (0x01 << 4) | (0x01 << 5) | (0x01 << 6)) != 0) {
+ printf(": can't switch %s pad\n", buf);
+ return;
+ }
+ if (sitara_cm_padconf_get(pin, &mode, &state) == 0) {
+ printf(": %s state %d ", mode, state);
+ }
+ }
+
+ rev = I2C_READ_REG(sc, AM335X_I2C_REVNB_LO);
+ printf(" rev %d.%d\n",
+ (int)I2C_REVNB_LO_MAJOR(rev),
+ (int)I2C_REVNB_LO_MINOR(rev));
+
+ ti_iic_reset(sc);
+ ti_iic_flush(sc);
+
+ sc->sc_ic.ic_cookie = sc;
+ sc->sc_ic.ic_acquire_bus = ti_iic_acquire_bus;
+ sc->sc_ic.ic_release_bus = ti_iic_release_bus;
+ sc->sc_ic.ic_exec = ti_iic_exec;
+
+ bzero(&iba, sizeof iba);
+ iba.iba_name = "iic";
+ iba.iba_tag = &sc->sc_ic;
+ (void) config_found(&sc->sc_dev, &iba, iicbus_print);
+}
+
+static int
+ti_iic_intr(void *arg)
+{
+ struct ti_iic_softc *sc = arg;
+ uint32_t stat;
+
+ DPRINTF(("ti_iic_intr\n"));
+ stat = I2C_READ_REG(sc, AM335X_I2C_IRQSTATUS);
+ I2C_WRITE_REG(sc, AM335X_I2C_IRQSTATUS, stat);
+ DPRINTF(("ti_iic_intr pre handle sc->sc_op eq %#x\n", sc->sc_op));
+
+ ti_iic_handle_intr(sc, stat);
+
+ if (sc->sc_op == TI_I2CERROR || sc->sc_op == TI_I2CDONE) {
+ DPRINTF(("ti_iic_intr post handle sc->sc_op %#x\n", sc->sc_op));
+ wakeup(&sc->sc_dev);
+ }
+
+ DPRINTF(("ti_iic_intr status 0x%x\n", stat));
+
+ return 1;
+}
+
+static int
+ti_iic_acquire_bus(void *opaque, int flags)
+{
+ struct ti_iic_softc *sc = opaque;
+
+ if (flags & I2C_F_POLL)
+ return 0;
+
+ return (rw_enter(&sc->sc_buslock, RW_WRITE));
+}
+
+static void
+ti_iic_release_bus(void *opaque, int flags)
+{
+ struct ti_iic_softc *sc = opaque;
+
+ if (flags & I2C_F_POLL)
+ return;
+
+ rw_exit(&sc->sc_buslock);
+}
+
+static int
+ti_iic_exec(void *opaque, i2c_op_t op, i2c_addr_t addr,
+ const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
+{
+ struct ti_iic_softc *sc = opaque;
+ int err;
+
+
+ DPRINTF(("ti_iic_exec: op 0x%x cmdlen %zd len %zd flags 0x%x\n",
+ op, cmdlen, len, flags));
+
+#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
+ if (cmdlen > 0) {
+ err = ti_iic_op(sc, addr, TI_I2CWRITE, __UNCONST(cmdbuf),
+ cmdlen, (I2C_OP_READ_P(op) ? 0 : I2C_F_STOP) | flags);
+ if (err)
+ goto done;
+ }
+ if (I2C_OP_STOP_P(op))
+ flags |= I2C_F_STOP;
+
+ /*
+ * I2C controller doesn't allow for zero-byte transfers.
+ */
+ if (len == 0)
+ goto done;
+
+ if (I2C_OP_READ_P(op))
+ err = ti_iic_op(sc, addr, TI_I2CREAD, buf, len, flags);
+ else
+ err = ti_iic_op(sc, addr, TI_I2CWRITE, buf, len, flags);
+
+done:
+ if (err)
+ ti_iic_reset(sc);
+
+ ti_iic_flush(sc);
+
+ DPRINTF(("ti_iic_exec: done %d\n", err));
+ return err;
+}
+
+static int
+ti_iic_reset(struct ti_iic_softc *sc)
+{
+ uint32_t psc, scll, sclh;
+ int i;
+
+ DPRINTF(("ti_iic_reset\n"));
+
+ /* Disable */
+ I2C_WRITE_REG(sc, AM335X_I2C_CON, 0);
+ /* Soft reset */
+ I2C_WRITE_REG(sc, AM335X_I2C_SYSC, I2C_SYSC_SRST);
+ delay(1000);
+ /* enable so that we can check for reset complete */
+ I2C_WRITE_REG(sc, AM335X_I2C_CON, I2C_CON_EN);
+ delay(1000);
+ for (i = 0; i < 1000; i++) { /* 1s delay for reset */
+ if (I2C_READ_REG(sc, AM335X_I2C_SYSS) & I2C_SYSS_RDONE)
+ break;
+ }
+ /* Disable again */
+ I2C_WRITE_REG(sc, AM335X_I2C_CON, 0);
+ delay(50000);
+
+ if (i >= 1000) {
+ printf("%s: couldn't reset module\n", DEVNAME(sc));
+ return 1;
+ }
+
+ /* XXX standard speed only */
+ psc = 3;
+ scll = 53;
+ sclh = 55;
+
+ /* Clocks */
+ I2C_WRITE_REG(sc, AM335X_I2C_PSC, psc);
+ I2C_WRITE_REG(sc, AM335X_I2C_SCLL, scll);
+ I2C_WRITE_REG(sc, AM335X_I2C_SCLH, sclh);
+
+ /* Own I2C address */
+ I2C_WRITE_REG(sc, AM335X_I2C_OA, AM335X_I2C_SLAVE_ADDR);
+
+ /* 5 bytes fifo */
+ I2C_WRITE_REG(sc, AM335X_I2C_BUF,
+ I2C_BUF_RXTRSH(sc->sc_rxthres) | I2C_BUF_TXTRSH(sc->sc_txthres));
+
+ /* Enable */
+ I2C_WRITE_REG(sc, AM335X_I2C_CON, I2C_CON_EN);
+
+ return 0;
+}
+
+static int
+ti_iic_op(struct ti_iic_softc *sc, i2c_addr_t addr, ti_i2cop_t op,
+ uint8_t *buf, size_t buflen, int flags)
+{
+ uint16_t con, stat, mask;
+ int err, retry;
+
+ KASSERT(op == TI_I2CREAD || op == TI_I2CWRITE);
+ DPRINTF(("ti_iic_op: addr %#x op %#x buf %p buflen %#x flags %#x\n",
+ addr, op, buf, (unsigned int) buflen, flags));
+
+ mask = I2C_IRQSTATUS_ARDY | I2C_IRQSTATUS_NACK | I2C_IRQSTATUS_AL;
+ if (op == TI_I2CREAD)
+ mask |= I2C_IRQSTATUS_RDR | I2C_IRQSTATUS_RRDY;
+ else
+ mask |= I2C_IRQSTATUS_XDR | I2C_IRQSTATUS_XRDY;
+
+ err = ti_iic_wait(sc, I2C_IRQSTATUS_BB, 0, flags);
+ if (err) {
+ DPRINTF(("ti_iic_op: wait error %d\n", err));
+ return err;
+ }
+
+ con = I2C_CON_EN;
+ con |= I2C_CON_MST;
+ con |= I2C_CON_STT;
+ if (flags & I2C_F_STOP)
+ con |= I2C_CON_STP;
+ if (addr & ~0x7f)
+ con |= I2C_CON_XSA;
+ if (op == TI_I2CWRITE)
+ con |= I2C_CON_TRX;
+
+ sc->sc_op = op;
+ sc->sc_buf = buf;
+ sc->sc_buflen = buflen;
+ sc->sc_bufidx = 0;
+
+ I2C_WRITE_REG(sc,
+ AM335X_I2C_CON, I2C_CON_EN | I2C_CON_MST | I2C_CON_STP);
+ DPRINTF(("ti_iic_op: op %d con 0x%x ", op, con));
+ I2C_WRITE_REG(sc, AM335X_I2C_CNT, buflen);
+ I2C_WRITE_REG(sc, AM335X_I2C_SA, (addr & I2C_SA_MASK));
+ DPRINTF(("SA 0x%x len %d\n",
+ I2C_READ_REG(sc, AM335X_I2C_SA), I2C_READ_REG(sc, AM335X_I2C_CNT)));
+
+ if ((flags & I2C_F_POLL) == 0) {
+ /* clear any pending interrupt */
+ I2C_WRITE_REG(sc, AM335X_I2C_IRQSTATUS,
+ I2C_READ_REG(sc, AM335X_I2C_IRQSTATUS));
+ /* and enable */
+ I2C_WRITE_REG(sc, AM335X_I2C_IRQENABLE_SET, mask);
+ }
+ /* start transfer */
+ I2C_WRITE_REG(sc, AM335X_I2C_CON, con);
+
+ if ((flags & I2C_F_POLL) == 0) {
+ /* and wait for completion */
+ DPRINTF(("ti_iic_op waiting, op %#x\n", sc->sc_op));
+ while (sc->sc_op == op) {
+ if (tsleep(&sc->sc_dev, PWAIT, "tiiic", 500)
+ == EWOULDBLOCK) {
+ /* timeout */
+ op = TI_I2CERROR;
+ }
+ }
+ DPRINTF(("ti_iic_op waiting done, op %#x\n", sc->sc_op));
+
+ /* disable interrupts */
+ I2C_WRITE_REG(sc, AM335X_I2C_IRQENABLE_CLR, 0xffff);
+ } else {
+ /* poll for completion */
+ DPRINTF(("ti_iic_op polling, op %x\n", sc->sc_op));
+ while (sc->sc_op == op) {
+ stat = ti_iic_stat(sc, mask);
+ DPRINTF(("ti_iic_op stat 0x%x\n", stat));
+ if (stat == 0) /* timeout */
+ sc->sc_op = TI_I2CERROR;
+ else
+ ti_iic_handle_intr(sc, stat);
+ I2C_WRITE_REG(sc, AM335X_I2C_IRQSTATUS, stat);
+ }
+ DPRINTF(("ti_iic_op polling done, op now %x\n", sc->sc_op));
+ }
+ retry = 10000;
+ I2C_WRITE_REG(sc, AM335X_I2C_CON, 0);
+ while (I2C_READ_REG(sc, AM335X_I2C_CON) & I2C_CON_MST) {
+ delay(100);
+ if (--retry == 0)
+ break;
+ }
+
+ return (sc->sc_op == TI_I2CDONE) ? 0 : EIO;
+}
+
+static void
+ti_iic_handle_intr(struct ti_iic_softc *sc, uint32_t stat)
+{
+ KASSERT(stat != 0);
+ DPRINTF(("ti_iic_handle_intr stat %#x\n", stat));
+
+ if (stat & (I2C_IRQSTATUS_NACK|I2C_IRQSTATUS_AL)) {
+ sc->sc_op = TI_I2CERROR;
+ return;
+ }
+ if (stat & I2C_IRQSTATUS_ARDY) {
+ sc->sc_op = TI_I2CDONE;
+ return;
+ }
+ if (sc->sc_op == TI_I2CREAD)
+ ti_iic_do_read(sc, stat);
+ else if (sc->sc_op == TI_I2CWRITE)
+ ti_iic_do_write(sc, stat);
+ else
+ return;
+}
+void
+ti_iic_do_read(struct ti_iic_softc *sc, uint32_t stat)
+{
+ int len = 0;
+
+ DPRINTF(("ti_iic_do_read stat %#x\n", stat));
+ if (stat & I2C_IRQSTATUS_RDR) {
+ len = I2C_READ_REG(sc, AM335X_I2C_BUFSTAT);
+ len = I2C_BUFSTAT_RXSTAT(len);
+ DPRINTF(("ti_iic_do_read receive drain len %d left %d\n",
+ len, I2C_READ_REG(sc, AM335X_I2C_CNT)));
+ } else if (stat & I2C_IRQSTATUS_RRDY) {
+ len = sc->sc_rxthres + 1;
+ DPRINTF(("ti_iic_do_read receive len %d left %d\n",
+ len, I2C_READ_REG(sc, AM335X_I2C_CNT)));
+ }
+ for (;
+ sc->sc_bufidx < sc->sc_buflen && len > 0;
+ sc->sc_bufidx++, len--) {
+ sc->sc_buf[sc->sc_bufidx] = I2C_READ_DATA(sc);
+ DPRINTF(("ti_iic_do_read got b[%d]=0x%x\n", sc->sc_bufidx,
+ sc->sc_buf[sc->sc_bufidx]));
+ }
+ DPRINTF(("ti_iic_do_read done\n"));
+}
+
+void
+ti_iic_do_write(struct ti_iic_softc *sc, uint32_t stat)
+{
+ int len = 0;
+
+ DPRINTF(("ti_iic_do_write stat %#x\n", stat));
+
+ if (stat & I2C_IRQSTATUS_XDR) {
+ len = I2C_READ_REG(sc, AM335X_I2C_BUFSTAT);
+ len = I2C_BUFSTAT_TXSTAT(len);
+ DPRINTF(("ti_iic_do_write xmit drain len %d left %d\n",
+ len, I2C_READ_REG(sc, AM335X_I2C_CNT)));
+ } else if (stat & I2C_IRQSTATUS_XRDY) {
+ len = sc->sc_txthres + 1;
+ DPRINTF(("ti_iic_do_write xmit len %d left %d\n",
+ len, I2C_READ_REG(sc, AM335X_I2C_CNT)));
+ }
+ for (;
+ sc->sc_bufidx < sc->sc_buflen && len > 0;
+ sc->sc_bufidx++, len--) {
+ DPRINTF(("ti_iic_do_write send b[%d]=0x%x\n",
+ sc->sc_bufidx, sc->sc_buf[sc->sc_bufidx]));
+ I2C_WRITE_DATA(sc, sc->sc_buf[sc->sc_bufidx]);
+ }
+ DPRINTF(("ti_iic_do_write done\n"));
+}
+
+static int
+ti_iic_wait(struct ti_iic_softc *sc, uint16_t mask, uint16_t val, int flags)
+{
+ int retry = 10;
+ uint16_t v;
+ DPRINTF(("ti_iic_wait mask %#x val %#x flags %#x\n", mask, val, flags));
+
+ while (((v = I2C_READ_REG(sc, AM335X_I2C_IRQSTATUS_RAW)) & mask) != val) {
+ --retry;
+ if (retry == 0) {
+ printf("%s: wait timeout, mask=%#x val=%#x stat=%#x\n",
+ DEVNAME(sc), mask, val, v);
+ return EBUSY;
+ }
+ if (flags & I2C_F_POLL)
+ delay(50000);
+ else
+ tsleep(&sc->sc_dev, PWAIT, "tiiic", 50);
+ }
+ DPRINTF(("ti_iic_wait done retry %#x\n", retry));
+
+ return 0;
+}
+
+static uint32_t
+ti_iic_stat(struct ti_iic_softc *sc, uint32_t mask)
+{
+ uint32_t v;
+ int retry = 500;
+ DPRINTF(("ti_iic_wait mask %#x\n", mask));
+ while (--retry > 0) {
+ v = I2C_READ_REG(sc, AM335X_I2C_IRQSTATUS_RAW) & mask;
+ if (v != 0)
+ break;
+ delay(100);
+ }
+ DPRINTF(("ti_iic_wait done retry %#x\n", retry));
+ return v;
+}
+
+static int
+ti_iic_flush(struct ti_iic_softc *sc)
+{
+ DPRINTF(("ti_iic_flush\n"));
+#if 0
+ int retry = 1000;
+ uint16_t v;
+
+ while ((v =
+ I2C_READ_REG(sc, AM335X_I2C_IRQSTATUS_RAW)) & I2C_IRQSTATUS_RRDY) {
+ if (--retry == 0) {
+ printf("%s: flush timeout, stat = %#x\n", DEVNAME(sc), v);
+ return EBUSY;
+ }
+ (void)I2C_READ_DATA(sc);
+ delay(1000);
+ }
+#endif
+
+ I2C_WRITE_REG(sc, AM335X_I2C_CNT, 0);
+ return 0;
+}
--- /dev/null
+/* $OpenBSD: ti_iicreg.h,v 1.1 2013/11/24 15:00:22 rapha Exp $ */
+/* $NetBSD: ti_iicreg.h,v 1.1 2013/04/17 14:33:06 bouyer Exp $ */
+
+/*
+ * Copyright (c) 2013 Manuel Bouyer. 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 ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* register definitions for the i2c controller found in the
+ * Texas Instrument AM335x SOC
+ */
+
+#ifndef _AM335XIICREG_H
+#define _AM335XIICREG_H
+
+#define AM335X_I2C_REVNB_LO 0x00
+#define I2C_REVNB_LO_RTL(x) (((x) >> 11) & 0x01f)
+#define I2C_REVNB_LO_MAJOR(x) (((x) >> 8) & 0x007)
+#define I2C_REVNB_LO_CUSTOM(x) (((x) >> 6) & 0x003)
+#define I2C_REVNB_LO_MINOR(x) (((x) >> 0) & 0x01f)
+#define AM335X_I2C_REVNB_HI 0x04
+#define I2C_REVNB_HI_SCHEME(x) (((x) >> 14) & 0x003)
+#define I2C_REVNB_HI_FUNC(x) (((x) >> 0) & 0xfff)
+#define AM335X_I2C_SYSC 0x10
+#define I2C_SYSC_CLKACTIVITY_OCP 0x0010
+#define I2C_SYSC_CLKACTIVITY_SYSTEM 0x0020
+#define I2C_SYSC_IDLE_MASK 0x0018
+#define I2C_SYSC_IDLE_FORCE 0x0000
+#define I2C_SYSC_IDLE_SMART 0x0010
+#define I2C_SYSC_IDLE_NONE 0x0008
+#define I2C_SYSC_ENAWAKEUP 0x0004
+#define I2C_SYSC_SRST 0x0002
+#define I2C_SYSC_AUTOIDLE 0x0001
+#define AM335X_I2C_IRQSTATUS_RAW 0x24
+#define AM335X_I2C_IRQSTATUS 0x28
+#define AM335X_I2C_IRQENABLE_SET 0x2C
+#define AM335X_I2C_IRQENABLE_CLR 0x30
+#define AM335X_I2C_WE 0x34
+#define I2C_IRQSTATUS_XDR 0x4000
+#define I2C_IRQSTATUS_RDR 0x2000
+#define I2C_IRQSTATUS_BB 0x1000
+#define I2C_IRQSTATUS_ROVR 0x0800
+#define I2C_IRQSTATUS_XUDF 0x0400
+#define I2C_IRQSTATUS_AAS 0x0200
+#define I2C_IRQSTATUS_BF 0x0100
+#define I2C_IRQSTATUS_AERR 0x0080
+#define I2C_IRQSTATUS_STC 0x0040
+#define I2C_IRQSTATUS_GC 0x0020
+#define I2C_IRQSTATUS_XRDY 0x0010
+#define I2C_IRQSTATUS_RRDY 0x0008
+#define I2C_IRQSTATUS_ARDY 0x0004
+#define I2C_IRQSTATUS_NACK 0x0002
+#define I2C_IRQSTATUS_AL 0x0001
+#define AM335X_I2C_DMARXENABLE_SET 0x38
+#define AM335X_I2C_DMATXENABLE_SET 0x3C
+#define AM335X_I2C_DMARXENABLE_CLR 0x40
+#define I2C_DMARXENABLE 0x0001
+#define AM335X_I2C_DMATXENABLE_CLR 0x44
+#define I2C_DMATXENABLE 0x0001
+#define AM335X_I2C_DMARXWAKE_EN 0x48
+ /* use same bits as IRQ */
+#define AM335X_I2C_DMATXWAKE_EN 0x4C
+ /* use same bits as IRQ */
+#define AM335X_I2C_SYSS 0x90
+#define I2C_SYSS_RDONE 0x0001
+#define AM335X_I2C_BUF 0x94
+#define I2C_BUF_RDMA_EN 0x8000
+#define I2C_BUF_RXFIFO_CLR 0x4000
+#define I2C_BUF_RXTRSH_MASK 0x3f00
+#define I2C_BUF_RXTRSH(x) ((x) << 8)
+#define I2C_BUF_XDMA_EN 0x0080
+#define I2C_BUF_TXFIFO_CLR 0x0040
+#define I2C_BUF_TXTRSH_MASK 0x003f
+#define I2C_BUF_TXTRSH(x) ((x) << 0)
+#define AM335X_I2C_CNT 0x98
+#define I2C_CNT_MASK 0xffff
+#define AM335X_I2C_DATA 0x9C
+#define I2C_DATA_MASK 0x00ff
+#define AM335X_I2C_CON 0xA4
+#define I2C_CON_EN 0x8000
+#define I2C_CON_STB 0x0800
+#define I2C_CON_MST 0x0400
+#define I2C_CON_TRX 0x0200
+#define I2C_CON_XSA 0x0100
+#define I2C_CON_XOA0 0x0080
+#define I2C_CON_XOA1 0x0040
+#define I2C_CON_XOA2 0x0020
+#define I2C_CON_XOA3 0x0010
+#define I2C_CON_STP 0x0002
+#define I2C_CON_STT 0x0001
+#define AM335X_I2C_OA 0xA8
+#define I2C_OA_MASK 0x03ff
+#define AM335X_I2C_SA 0xAC
+#define I2C_SA_MASK 0x03ff
+#define AM335X_I2C_PSC 0xB0
+#define I2C_PSC_MASK 0x000f
+#define AM335X_I2C_SCLL 0xB4
+#define I2C_SCLL_MASK 0x000f
+#define AM335X_I2C_SCLH 0xB8
+#define I2C_SCLH_MASK 0x000f
+#define AM335X_I2C_SYSTEST 0xBC
+#define AM335X_I2C_BUFSTAT 0xC0
+#define I2C_BUFSTAT_FIFODEPTH(x) (((x) >> 14) & 0x03)
+#define I2C_BUFSTAT_RXSTAT(x) (((x) >> 8) & 0x3f)
+#define I2C_BUFSTAT_TXSTAT(x) (((x) >> 0) & 0x3f)
+#define AM335X_I2C_OA1 0xC4
+#define AM335X_I2C_OA2 0xC8
+#define AM335X_I2C_OA3 0xCC
+ /* same bits as I2C_OA */
+#define AM335X_I2C_ACTOA 0xD0
+#define AM335X_I2C_SBLOCK 0xD4
+#define I2C_ACTOA_OA3_ACT 0x0008
+#define I2C_ACTOA_OA2_ACT 0x0004
+#define I2C_ACTOA_OA1_ACT 0x0002
+#define I2C_ACTOA_OA0_ACT 0x0001
+
+#endif /* _AM335XIICREG_H */