linux/arch/arm/mach-imx/mx31moboard-marxbot.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
   4 */
   5
   6#include <linux/delay.h>
   7#include <linux/gpio.h>
   8#include <linux/init.h>
   9#include <linux/interrupt.h>
  10#include <linux/i2c.h>
  11#include <linux/spi/spi.h>
  12#include <linux/slab.h>
  13#include <linux/platform_device.h>
  14#include <linux/types.h>
  15
  16#include <linux/usb/otg.h>
  17
  18#include "board-mx31moboard.h"
  19#include "common.h"
  20#include "devices-imx31.h"
  21#include "ehci.h"
  22#include "hardware.h"
  23#include "iomux-mx3.h"
  24#include "ulpi.h"
  25
  26static unsigned int marxbot_pins[] = {
  27        /* SDHC2 */
  28        MX31_PIN_PC_PWRON__SD2_DATA3, MX31_PIN_PC_VS1__SD2_DATA2,
  29        MX31_PIN_PC_READY__SD2_DATA1, MX31_PIN_PC_WAIT_B__SD2_DATA0,
  30        MX31_PIN_PC_CD2_B__SD2_CLK, MX31_PIN_PC_CD1_B__SD2_CMD,
  31        MX31_PIN_ATA_DIOR__GPIO3_28, MX31_PIN_ATA_DIOW__GPIO3_29,
  32        /* dsPIC resets */
  33        MX31_PIN_STXD5__GPIO1_21, MX31_PIN_SRXD5__GPIO1_22,
  34        /*battery detection */
  35        MX31_PIN_LCS0__GPIO3_23,
  36        /* USB H1 */
  37        MX31_PIN_CSPI1_MISO__USBH1_RXDP, MX31_PIN_CSPI1_MOSI__USBH1_RXDM,
  38        MX31_PIN_CSPI1_SS0__USBH1_TXDM, MX31_PIN_CSPI1_SS1__USBH1_TXDP,
  39        MX31_PIN_CSPI1_SS2__USBH1_RCV, MX31_PIN_CSPI1_SCLK__USBH1_OEB,
  40        MX31_PIN_CSPI1_SPI_RDY__USBH1_FS, MX31_PIN_SFS6__USBH1_SUSPEND,
  41        MX31_PIN_NFRE_B__GPIO1_11, MX31_PIN_NFALE__GPIO1_12,
  42        /* SEL */
  43        MX31_PIN_DTR_DCE1__GPIO2_8, MX31_PIN_DSR_DCE1__GPIO2_9,
  44        MX31_PIN_RI_DCE1__GPIO2_10, MX31_PIN_DCD_DCE1__GPIO2_11,
  45};
  46
  47#define SDHC2_CD IOMUX_TO_GPIO(MX31_PIN_ATA_DIOR)
  48#define SDHC2_WP IOMUX_TO_GPIO(MX31_PIN_ATA_DIOW)
  49
  50static int marxbot_sdhc2_get_ro(struct device *dev)
  51{
  52        return !gpio_get_value(SDHC2_WP);
  53}
  54
  55static int marxbot_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
  56                void *data)
  57{
  58        int ret;
  59
  60        ret = gpio_request(SDHC2_CD, "sdhc-detect");
  61        if (ret)
  62                return ret;
  63
  64        gpio_direction_input(SDHC2_CD);
  65
  66        ret = gpio_request(SDHC2_WP, "sdhc-wp");
  67        if (ret)
  68                goto err_gpio_free;
  69        gpio_direction_input(SDHC2_WP);
  70
  71        ret = request_irq(gpio_to_irq(SDHC2_CD), detect_irq,
  72                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  73                "sdhc2-card-detect", data);
  74        if (ret)
  75                goto err_gpio_free_2;
  76
  77        return 0;
  78
  79err_gpio_free_2:
  80        gpio_free(SDHC2_WP);
  81err_gpio_free:
  82        gpio_free(SDHC2_CD);
  83
  84        return ret;
  85}
  86
  87static void marxbot_sdhc2_exit(struct device *dev, void *data)
  88{
  89        free_irq(gpio_to_irq(SDHC2_CD), data);
  90        gpio_free(SDHC2_WP);
  91        gpio_free(SDHC2_CD);
  92}
  93
  94static const struct imxmmc_platform_data sdhc2_pdata __initconst = {
  95        .get_ro = marxbot_sdhc2_get_ro,
  96        .init   = marxbot_sdhc2_init,
  97        .exit   = marxbot_sdhc2_exit,
  98};
  99
 100#define TRSLAT_RST_B    IOMUX_TO_GPIO(MX31_PIN_STXD5)
 101#define DSPICS_RST_B    IOMUX_TO_GPIO(MX31_PIN_SRXD5)
 102
 103static void dspics_resets_init(void)
 104{
 105        if (!gpio_request(TRSLAT_RST_B, "translator-rst")) {
 106                gpio_direction_output(TRSLAT_RST_B, 0);
 107                gpio_export(TRSLAT_RST_B, false);
 108        }
 109
 110        if (!gpio_request(DSPICS_RST_B, "dspics-rst")) {
 111                gpio_direction_output(DSPICS_RST_B, 0);
 112                gpio_export(DSPICS_RST_B, false);
 113        }
 114}
 115
 116static struct spi_board_info marxbot_spi_board_info[] __initdata = {
 117        {
 118                .modalias = "spidev",
 119                .max_speed_hz = 300000,
 120                .bus_num = 1,
 121                .chip_select = 1, /* according spi1_cs[] ! */
 122        },
 123};
 124
 125#define SEL0 IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1)
 126#define SEL1 IOMUX_TO_GPIO(MX31_PIN_DSR_DCE1)
 127#define SEL2 IOMUX_TO_GPIO(MX31_PIN_RI_DCE1)
 128#define SEL3 IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)
 129
 130static void marxbot_init_sel_gpios(void)
 131{
 132        if (!gpio_request(SEL0, "sel0")) {
 133                gpio_direction_input(SEL0);
 134                gpio_export(SEL0, true);
 135        }
 136
 137        if (!gpio_request(SEL1, "sel1")) {
 138                gpio_direction_input(SEL1);
 139                gpio_export(SEL1, true);
 140        }
 141
 142        if (!gpio_request(SEL2, "sel2")) {
 143                gpio_direction_input(SEL2);
 144                gpio_export(SEL2, true);
 145        }
 146
 147        if (!gpio_request(SEL3, "sel3")) {
 148                gpio_direction_input(SEL3);
 149                gpio_export(SEL3, true);
 150        }
 151}
 152
 153#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
 154                        PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 155
 156static int marxbot_usbh1_hw_init(struct platform_device *pdev)
 157{
 158        mxc_iomux_set_gpr(MUX_PGP_USB_SUSPEND, true);
 159
 160        mxc_iomux_set_pad(MX31_PIN_CSPI1_MISO, USB_PAD_CFG);
 161        mxc_iomux_set_pad(MX31_PIN_CSPI1_MOSI, USB_PAD_CFG);
 162        mxc_iomux_set_pad(MX31_PIN_CSPI1_SS0, USB_PAD_CFG);
 163        mxc_iomux_set_pad(MX31_PIN_CSPI1_SS1, USB_PAD_CFG);
 164        mxc_iomux_set_pad(MX31_PIN_CSPI1_SS2, USB_PAD_CFG);
 165        mxc_iomux_set_pad(MX31_PIN_CSPI1_SCLK, USB_PAD_CFG);
 166        mxc_iomux_set_pad(MX31_PIN_CSPI1_SPI_RDY, USB_PAD_CFG);
 167        mxc_iomux_set_pad(MX31_PIN_SFS6, USB_PAD_CFG);
 168
 169        mdelay(10);
 170
 171        return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
 172                        MXC_EHCI_INTERFACE_SINGLE_UNI);
 173}
 174
 175#define USBH1_VBUSEN_B  IOMUX_TO_GPIO(MX31_PIN_NFRE_B)
 176#define USBH1_MODE      IOMUX_TO_GPIO(MX31_PIN_NFALE)
 177
 178static int marxbot_isp1105_init(struct usb_phy *otg)
 179{
 180        int ret = gpio_request(USBH1_MODE, "usbh1-mode");
 181        if (ret)
 182                return ret;
 183        /* single ended */
 184        gpio_direction_output(USBH1_MODE, 0);
 185
 186        ret = gpio_request(USBH1_VBUSEN_B, "usbh1-vbusen");
 187        if (ret) {
 188                gpio_free(USBH1_MODE);
 189                return ret;
 190        }
 191        gpio_direction_output(USBH1_VBUSEN_B, 1);
 192
 193        return 0;
 194}
 195
 196
 197static int marxbot_isp1105_set_vbus(struct usb_otg *otg, bool on)
 198{
 199        if (on)
 200                gpio_set_value(USBH1_VBUSEN_B, 0);
 201        else
 202                gpio_set_value(USBH1_VBUSEN_B, 1);
 203
 204        return 0;
 205}
 206
 207static struct mxc_usbh_platform_data usbh1_pdata __initdata = {
 208        .init   = marxbot_usbh1_hw_init,
 209        .portsc = MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
 210};
 211
 212static int __init marxbot_usbh1_init(void)
 213{
 214        struct usb_phy *phy;
 215        struct platform_device *pdev;
 216
 217        phy = kzalloc(sizeof(*phy), GFP_KERNEL);
 218        if (!phy)
 219                return -ENOMEM;
 220
 221        phy->otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
 222        if (!phy->otg) {
 223                kfree(phy);
 224                return -ENOMEM;
 225        }
 226
 227        phy->label      = "ISP1105";
 228        phy->init       = marxbot_isp1105_init;
 229        phy->otg->set_vbus      = marxbot_isp1105_set_vbus;
 230
 231        usbh1_pdata.otg = phy;
 232
 233        pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
 234
 235        return PTR_ERR_OR_ZERO(pdev);
 236}
 237
 238static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 239        .operating_mode = FSL_USB2_DR_DEVICE,
 240        .phy_mode       = FSL_USB2_PHY_ULPI,
 241};
 242
 243/*
 244 * system init for baseboard usage. Will be called by mx31moboard init.
 245 */
 246void __init mx31moboard_marxbot_init(void)
 247{
 248        printk(KERN_INFO "Initializing mx31marxbot peripherals\n");
 249
 250        mxc_iomux_setup_multiple_pins(marxbot_pins, ARRAY_SIZE(marxbot_pins),
 251                "marxbot");
 252
 253        marxbot_init_sel_gpios();
 254
 255        dspics_resets_init();
 256
 257        imx31_add_mxc_mmc(1, &sdhc2_pdata);
 258
 259        spi_register_board_info(marxbot_spi_board_info,
 260                ARRAY_SIZE(marxbot_spi_board_info));
 261
 262        /* battery present pin */
 263        gpio_request(IOMUX_TO_GPIO(MX31_PIN_LCS0), "bat-present");
 264        gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_LCS0));
 265        gpio_export(IOMUX_TO_GPIO(MX31_PIN_LCS0), false);
 266
 267        imx31_add_fsl_usb2_udc(&usb_pdata);
 268
 269        marxbot_usbh1_init();
 270}
 271