linux/arch/arm/mach-imx/mx31moboard-marxbot.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2 of the License, or
   7 * (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 */
  14
  15#include <linux/delay.h>
  16#include <linux/gpio.h>
  17#include <linux/init.h>
  18#include <linux/interrupt.h>
  19#include <linux/i2c.h>
  20#include <linux/spi/spi.h>
  21#include <linux/slab.h>
  22#include <linux/platform_device.h>
  23#include <linux/types.h>
  24
  25#include <linux/usb/otg.h>
  26
  27#include <media/soc_camera.h>
  28
  29#include "common.h"
  30#include "devices-imx31.h"
  31#include "ehci.h"
  32#include "hardware.h"
  33#include "iomux-mx3.h"
  34#include "ulpi.h"
  35
  36static unsigned int marxbot_pins[] = {
  37        /* SDHC2 */
  38        MX31_PIN_PC_PWRON__SD2_DATA3, MX31_PIN_PC_VS1__SD2_DATA2,
  39        MX31_PIN_PC_READY__SD2_DATA1, MX31_PIN_PC_WAIT_B__SD2_DATA0,
  40        MX31_PIN_PC_CD2_B__SD2_CLK, MX31_PIN_PC_CD1_B__SD2_CMD,
  41        MX31_PIN_ATA_DIOR__GPIO3_28, MX31_PIN_ATA_DIOW__GPIO3_29,
  42        /* CSI */
  43        MX31_PIN_CSI_D6__CSI_D6, MX31_PIN_CSI_D7__CSI_D7,
  44        MX31_PIN_CSI_D8__CSI_D8, MX31_PIN_CSI_D9__CSI_D9,
  45        MX31_PIN_CSI_D10__CSI_D10, MX31_PIN_CSI_D11__CSI_D11,
  46        MX31_PIN_CSI_D12__CSI_D12, MX31_PIN_CSI_D13__CSI_D13,
  47        MX31_PIN_CSI_D14__CSI_D14, MX31_PIN_CSI_D15__CSI_D15,
  48        MX31_PIN_CSI_HSYNC__CSI_HSYNC, MX31_PIN_CSI_MCLK__CSI_MCLK,
  49        MX31_PIN_CSI_PIXCLK__CSI_PIXCLK, MX31_PIN_CSI_VSYNC__CSI_VSYNC,
  50        MX31_PIN_CSI_D4__GPIO3_4, MX31_PIN_CSI_D5__GPIO3_5,
  51        MX31_PIN_GPIO3_0__GPIO3_0, MX31_PIN_GPIO3_1__GPIO3_1,
  52        MX31_PIN_TXD2__GPIO1_28,
  53        /* dsPIC resets */
  54        MX31_PIN_STXD5__GPIO1_21, MX31_PIN_SRXD5__GPIO1_22,
  55        /*battery detection */
  56        MX31_PIN_LCS0__GPIO3_23,
  57        /* USB H1 */
  58        MX31_PIN_CSPI1_MISO__USBH1_RXDP, MX31_PIN_CSPI1_MOSI__USBH1_RXDM,
  59        MX31_PIN_CSPI1_SS0__USBH1_TXDM, MX31_PIN_CSPI1_SS1__USBH1_TXDP,
  60        MX31_PIN_CSPI1_SS2__USBH1_RCV, MX31_PIN_CSPI1_SCLK__USBH1_OEB,
  61        MX31_PIN_CSPI1_SPI_RDY__USBH1_FS, MX31_PIN_SFS6__USBH1_SUSPEND,
  62        MX31_PIN_NFRE_B__GPIO1_11, MX31_PIN_NFALE__GPIO1_12,
  63        /* SEL */
  64        MX31_PIN_DTR_DCE1__GPIO2_8, MX31_PIN_DSR_DCE1__GPIO2_9,
  65        MX31_PIN_RI_DCE1__GPIO2_10, MX31_PIN_DCD_DCE1__GPIO2_11,
  66};
  67
  68#define SDHC2_CD IOMUX_TO_GPIO(MX31_PIN_ATA_DIOR)
  69#define SDHC2_WP IOMUX_TO_GPIO(MX31_PIN_ATA_DIOW)
  70
  71static int marxbot_sdhc2_get_ro(struct device *dev)
  72{
  73        return !gpio_get_value(SDHC2_WP);
  74}
  75
  76static int marxbot_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
  77                void *data)
  78{
  79        int ret;
  80
  81        ret = gpio_request(SDHC2_CD, "sdhc-detect");
  82        if (ret)
  83                return ret;
  84
  85        gpio_direction_input(SDHC2_CD);
  86
  87        ret = gpio_request(SDHC2_WP, "sdhc-wp");
  88        if (ret)
  89                goto err_gpio_free;
  90        gpio_direction_input(SDHC2_WP);
  91
  92        ret = request_irq(gpio_to_irq(SDHC2_CD), detect_irq,
  93                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  94                "sdhc2-card-detect", data);
  95        if (ret)
  96                goto err_gpio_free_2;
  97
  98        return 0;
  99
 100err_gpio_free_2:
 101        gpio_free(SDHC2_WP);
 102err_gpio_free:
 103        gpio_free(SDHC2_CD);
 104
 105        return ret;
 106}
 107
 108static void marxbot_sdhc2_exit(struct device *dev, void *data)
 109{
 110        free_irq(gpio_to_irq(SDHC2_CD), data);
 111        gpio_free(SDHC2_WP);
 112        gpio_free(SDHC2_CD);
 113}
 114
 115static const struct imxmmc_platform_data sdhc2_pdata __initconst = {
 116        .get_ro = marxbot_sdhc2_get_ro,
 117        .init   = marxbot_sdhc2_init,
 118        .exit   = marxbot_sdhc2_exit,
 119};
 120
 121#define TRSLAT_RST_B    IOMUX_TO_GPIO(MX31_PIN_STXD5)
 122#define DSPICS_RST_B    IOMUX_TO_GPIO(MX31_PIN_SRXD5)
 123
 124static void dspics_resets_init(void)
 125{
 126        if (!gpio_request(TRSLAT_RST_B, "translator-rst")) {
 127                gpio_direction_output(TRSLAT_RST_B, 0);
 128                gpio_export(TRSLAT_RST_B, false);
 129        }
 130
 131        if (!gpio_request(DSPICS_RST_B, "dspics-rst")) {
 132                gpio_direction_output(DSPICS_RST_B, 0);
 133                gpio_export(DSPICS_RST_B, false);
 134        }
 135}
 136
 137static struct spi_board_info marxbot_spi_board_info[] __initdata = {
 138        {
 139                .modalias = "spidev",
 140                .max_speed_hz = 300000,
 141                .bus_num = 1,
 142                .chip_select = 1, /* according spi1_cs[] ! */
 143        },
 144};
 145
 146#define TURRETCAM_POWER IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)
 147#define BASECAM_POWER   IOMUX_TO_GPIO(MX31_PIN_CSI_D5)
 148#define TURRETCAM_RST_B IOMUX_TO_GPIO(MX31_PIN_GPIO3_0)
 149#define BASECAM_RST_B   IOMUX_TO_GPIO(MX31_PIN_CSI_D4)
 150#define CAM_CHOICE      IOMUX_TO_GPIO(MX31_PIN_TXD2)
 151
 152static int marxbot_basecam_power(struct device *dev, int on)
 153{
 154        gpio_set_value(BASECAM_POWER, !on);
 155        return 0;
 156}
 157
 158static int marxbot_basecam_reset(struct device *dev)
 159{
 160        gpio_set_value(BASECAM_RST_B, 0);
 161        udelay(100);
 162        gpio_set_value(BASECAM_RST_B, 1);
 163        return 0;
 164}
 165
 166static struct i2c_board_info marxbot_i2c_devices[] = {
 167        {
 168                I2C_BOARD_INFO("mt9t031", 0x5d),
 169        },
 170};
 171
 172static struct soc_camera_link base_iclink = {
 173        .bus_id         = 0,            /* Must match with the camera ID */
 174        .power          = marxbot_basecam_power,
 175        .reset          = marxbot_basecam_reset,
 176        .board_info     = &marxbot_i2c_devices[0],
 177        .i2c_adapter_id = 0,
 178};
 179
 180static struct platform_device marxbot_camera[] = {
 181        {
 182                .name   = "soc-camera-pdrv",
 183                .id     = 0,
 184                .dev    = {
 185                        .platform_data = &base_iclink,
 186                },
 187        },
 188};
 189
 190static struct platform_device *marxbot_cameras[] __initdata = {
 191        &marxbot_camera[0],
 192};
 193
 194static int __init marxbot_cam_init(void)
 195{
 196        int ret = gpio_request(CAM_CHOICE, "cam-choice");
 197        if (ret)
 198                return ret;
 199        gpio_direction_output(CAM_CHOICE, 0);
 200
 201        ret = gpio_request(BASECAM_RST_B, "basecam-reset");
 202        if (ret)
 203                return ret;
 204        gpio_direction_output(BASECAM_RST_B, 1);
 205        ret = gpio_request(BASECAM_POWER, "basecam-standby");
 206        if (ret)
 207                return ret;
 208        gpio_direction_output(BASECAM_POWER, 0);
 209
 210        ret = gpio_request(TURRETCAM_RST_B, "turretcam-reset");
 211        if (ret)
 212                return ret;
 213        gpio_direction_output(TURRETCAM_RST_B, 1);
 214        ret = gpio_request(TURRETCAM_POWER, "turretcam-standby");
 215        if (ret)
 216                return ret;
 217        gpio_direction_output(TURRETCAM_POWER, 0);
 218
 219        return 0;
 220}
 221
 222#define SEL0 IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1)
 223#define SEL1 IOMUX_TO_GPIO(MX31_PIN_DSR_DCE1)
 224#define SEL2 IOMUX_TO_GPIO(MX31_PIN_RI_DCE1)
 225#define SEL3 IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)
 226
 227static void marxbot_init_sel_gpios(void)
 228{
 229        if (!gpio_request(SEL0, "sel0")) {
 230                gpio_direction_input(SEL0);
 231                gpio_export(SEL0, true);
 232        }
 233
 234        if (!gpio_request(SEL1, "sel1")) {
 235                gpio_direction_input(SEL1);
 236                gpio_export(SEL1, true);
 237        }
 238
 239        if (!gpio_request(SEL2, "sel2")) {
 240                gpio_direction_input(SEL2);
 241                gpio_export(SEL2, true);
 242        }
 243
 244        if (!gpio_request(SEL3, "sel3")) {
 245                gpio_direction_input(SEL3);
 246                gpio_export(SEL3, true);
 247        }
 248}
 249
 250#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
 251                        PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 252
 253static int marxbot_usbh1_hw_init(struct platform_device *pdev)
 254{
 255        mxc_iomux_set_gpr(MUX_PGP_USB_SUSPEND, true);
 256
 257        mxc_iomux_set_pad(MX31_PIN_CSPI1_MISO, USB_PAD_CFG);
 258        mxc_iomux_set_pad(MX31_PIN_CSPI1_MOSI, USB_PAD_CFG);
 259        mxc_iomux_set_pad(MX31_PIN_CSPI1_SS0, USB_PAD_CFG);
 260        mxc_iomux_set_pad(MX31_PIN_CSPI1_SS1, USB_PAD_CFG);
 261        mxc_iomux_set_pad(MX31_PIN_CSPI1_SS2, USB_PAD_CFG);
 262        mxc_iomux_set_pad(MX31_PIN_CSPI1_SCLK, USB_PAD_CFG);
 263        mxc_iomux_set_pad(MX31_PIN_CSPI1_SPI_RDY, USB_PAD_CFG);
 264        mxc_iomux_set_pad(MX31_PIN_SFS6, USB_PAD_CFG);
 265
 266        mdelay(10);
 267
 268        return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
 269                        MXC_EHCI_INTERFACE_SINGLE_UNI);
 270}
 271
 272#define USBH1_VBUSEN_B  IOMUX_TO_GPIO(MX31_PIN_NFRE_B)
 273#define USBH1_MODE      IOMUX_TO_GPIO(MX31_PIN_NFALE)
 274
 275static int marxbot_isp1105_init(struct usb_phy *otg)
 276{
 277        int ret = gpio_request(USBH1_MODE, "usbh1-mode");
 278        if (ret)
 279                return ret;
 280        /* single ended */
 281        gpio_direction_output(USBH1_MODE, 0);
 282
 283        ret = gpio_request(USBH1_VBUSEN_B, "usbh1-vbusen");
 284        if (ret) {
 285                gpio_free(USBH1_MODE);
 286                return ret;
 287        }
 288        gpio_direction_output(USBH1_VBUSEN_B, 1);
 289
 290        return 0;
 291}
 292
 293
 294static int marxbot_isp1105_set_vbus(struct usb_otg *otg, bool on)
 295{
 296        if (on)
 297                gpio_set_value(USBH1_VBUSEN_B, 0);
 298        else
 299                gpio_set_value(USBH1_VBUSEN_B, 1);
 300
 301        return 0;
 302}
 303
 304static struct mxc_usbh_platform_data usbh1_pdata __initdata = {
 305        .init   = marxbot_usbh1_hw_init,
 306        .portsc = MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
 307};
 308
 309static int __init marxbot_usbh1_init(void)
 310{
 311        struct usb_phy *phy;
 312        struct platform_device *pdev;
 313
 314        phy = kzalloc(sizeof(*phy), GFP_KERNEL);
 315        if (!phy)
 316                return -ENOMEM;
 317
 318        phy->otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
 319        if (!phy->otg) {
 320                kfree(phy);
 321                return -ENOMEM;
 322        }
 323
 324        phy->label      = "ISP1105";
 325        phy->init       = marxbot_isp1105_init;
 326        phy->otg->set_vbus      = marxbot_isp1105_set_vbus;
 327
 328        usbh1_pdata.otg = phy;
 329
 330        pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
 331
 332        return PTR_ERR_OR_ZERO(pdev);
 333}
 334
 335static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 336        .operating_mode = FSL_USB2_DR_DEVICE,
 337        .phy_mode       = FSL_USB2_PHY_ULPI,
 338};
 339
 340/*
 341 * system init for baseboard usage. Will be called by mx31moboard init.
 342 */
 343void __init mx31moboard_marxbot_init(void)
 344{
 345        printk(KERN_INFO "Initializing mx31marxbot peripherals\n");
 346
 347        mxc_iomux_setup_multiple_pins(marxbot_pins, ARRAY_SIZE(marxbot_pins),
 348                "marxbot");
 349
 350        marxbot_init_sel_gpios();
 351
 352        dspics_resets_init();
 353
 354        imx31_add_mxc_mmc(1, &sdhc2_pdata);
 355
 356        spi_register_board_info(marxbot_spi_board_info,
 357                ARRAY_SIZE(marxbot_spi_board_info));
 358
 359        marxbot_cam_init();
 360        platform_add_devices(marxbot_cameras, ARRAY_SIZE(marxbot_cameras));
 361
 362        /* battery present pin */
 363        gpio_request(IOMUX_TO_GPIO(MX31_PIN_LCS0), "bat-present");
 364        gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_LCS0));
 365        gpio_export(IOMUX_TO_GPIO(MX31_PIN_LCS0), false);
 366
 367        imx31_add_fsl_usb2_udc(&usb_pdata);
 368
 369        marxbot_usbh1_init();
 370}
 371