blob: 84bdbe7cd76afbdde96e92ace01be1e2f02ee36a [file] [log] [blame]
/*
* arch/arm/mach-ambarella/init-dropcam-cr.c
*
* Copyright (C) 2013, Dropcam, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-2557 USA
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/pda_power.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <plat/ambinput.h>
#include <mach/hardware.h>
#include <mach/init.h>
#include <mach/board.h>
#include "board-device.h"
#include <mach/init-dropcam.h>
#include <linux/leds-lp5523.h>
#include <linux/leds-lp5521.h>
#include "lp5523_progs.h"
#define EVT_B_TARGET 319
#define EVT_B_MIN (EVT_B_TARGET-30)
#define EVT_B_MAX (EVT_B_TARGET+30)
#define EVT_A_TARGET 203
#define EVT_A_MIN (EVT_A_TARGET-40)
#define EVT_A_MAX (EVT_A_TARGET+40)
/* ==========================================================================*/
static int ambarella_power_is_ac_online(void)
{
return 1;
}
static struct pda_power_pdata ambarella_power_supply_info = {
.is_ac_online = ambarella_power_is_ac_online,
};
static struct platform_device ambarella_power_supply = {
.name = "pda-power",
.id = -1,
.dev = {
.platform_data = &ambarella_power_supply_info,
},
};
/* ==========================================================================*/
static struct platform_device *ambarella_devices[] __initdata = {
&ambarella_adc0,
&ambarella_crypto,
// &ambarella_eth0,
&ambarella_fb0,
&ambarella_fb1,
&ambarella_i2s0,
&ambarella_pcm0,
&ambarella_dummy_codec0,
&ambarella_idc0,
&ambarella_idc1,
&ambarella_i2cmux,
// &ambarella_ir0,
&ambarella_sd0,
&ambarella_spi0,
&ambarella_spi1,
// &ambarella_spi_slave,
&ambarella_uart,
&ambarella_uart1,
&ambarella_udc0,
&ambarella_wdt0,
&ambarella_pwm_platform_device0,
&ambarella_pwm_platform_device1,
&ambarella_pwm_platform_device2,
&ambarella_pwm_platform_device3,
&ambarella_pwm_platform_device4,
&ambarella_power_supply,
&ambarella_fsg_device0,
&ambarella_usb_device0,
};
/* ==========================================================================*/
static struct spi_board_info ambarella_spi_devices[] = {
{
.modalias = "spidev",
.bus_num = 0,
.chip_select = 0,
},
{
.modalias = "spidev",
.bus_num = 0,
.chip_select = 1,
},
{
.modalias = "spidev",
.bus_num = 0,
.chip_select = 2,
},
{
.modalias = "spidev",
.bus_num = 0,
.chip_select = 3,
},
{
.modalias = "spidev",
.bus_num = 1,
.chip_select = 0,
}
};
/* ==========================================================================*/
static struct ambarella_key_table dropcam_keymap[AMBINPUT_TABLE_SIZE] = {
{AMBINPUT_VI_KEY, {.vi_key = {0, 0, 0}}},
{AMBINPUT_VI_REL, {.vi_rel = {0, 0, 0}}},
{AMBINPUT_VI_ABS, {.vi_abs = {0, 0, 0}}},
{AMBINPUT_VI_SW, {.vi_sw = {0, 0, 0}}},
{AMBINPUT_GPIO_KEY, {.gpio_key = {KEY_CONFIG, 0, 1, GPIO(35), IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING}}},
{AMBINPUT_END}
};
static struct ambarella_input_board_info dropcam_board_input_info = {
.pkeymap = dropcam_keymap,
.pinput_dev = NULL,
.pdev = NULL,
.abx_max_x = 4095,
.abx_max_y = 4095,
.abx_max_pressure = 4095,
.abx_max_width = 16,
};
static struct platform_device dropcam_board_input = {
.name = "ambarella-input",
.id = -1,
.resource = NULL,
.num_resources = 0,
.dev = {
.platform_data = &dropcam_board_input_info,
.dma_mask = &ambarella_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
}
};
/* ==========================================================================*/
static const int GPIO1_AFSEL_1 = 33;
static const int GPIO1_AFSEL_2 = 34;
static const int BT_HOST_WAKE_GPIO = 43;
static const int ZIG_EN = 44;
static const int BT_RST_GPIO = 42;
static const int BT_RF_DISABLE_GPIO = 40;
static const int BT_WAKE_GPIO = 4;
static struct lp5523_led_config lp5523_led_config_evt_a[] = {
{
.chan_nr = 0,
.led_current = 255,
.max_current = 255,
.default_value = 0,
},
{
.chan_nr = 1,
.led_current = 255,
.max_current = 255,
.default_value = 0,
},
{
.chan_nr = 2,
.led_current = 255,
.max_current = 255,
.default_value = 0,
},
{
.chan_nr = 3,
.led_current = 255,
.max_current = 255,
.default_value = 0,
},
{
.chan_nr = 4,
.led_current = 255,
.max_current = 255,
.default_value = 0,
},
{
.chan_nr = 5,
.led_current = 255,
.max_current = 255,
.default_value = 0,
},
{
.chan_nr = 6,
.led_current = 255,
.max_current = 255,
.default_value = 0,
},
{
.chan_nr = 7,
.led_current = 255,
.max_current = 255,
.default_value = 0,
}
};
static struct lp5523_led_config lp5523_led_config_evt_b[] = {
{
.chan_nr = 0,
.led_current = 255,
.max_current = 255,
.default_value = 255,
},
{
.chan_nr = 1,
.led_current = 255,
.max_current = 255,
.default_value = 255,
},
{
.chan_nr = 2,
.led_current = 255,
.max_current = 255,
.default_value = 255,
},
{
.chan_nr = 3,
.led_current = 255,
.max_current = 255,
.default_value = 255,
},
{
.chan_nr = 4,
.led_current = 255,
.max_current = 255,
.default_value = 255,
},
{
.chan_nr = 5,
.led_current = 255,
.max_current = 255,
.default_value = 255,
},
{
.chan_nr = 6,
.led_current = 255,
.max_current = 255,
.default_value = 255,
},
{
.chan_nr = 7,
.led_current = 255,
.max_current = 255,
.default_value = 255,
},
{
.chan_nr = 8,
.led_current = 255,
.max_current = 255,
.default_value = 0,
}
};
static struct lp5523_engine_config lp5523_engine_config = {
.engine1_mode = LP5523_CMD_RUN,
.engine2_mode = LP5523_CMD_RUN,
.engine3_mode = LP5523_CMD_RUN,
};
#define GPIO_LP5523_ENABLE 47
static void lp5523_enable(bool state)
{
/* EVT_A uses enable */
if (dropcam_get_hw_rev_adc_val() > EVT_A_MIN && dropcam_get_hw_rev_adc_val() < EVT_A_MAX) {
if (state) {
ambarella_gpio_config(GPIO_LP5523_ENABLE, GPIO_FUNC_SW_OUTPUT);
ambarella_gpio_set(GPIO_LP5523_ENABLE, 1);
} else {
ambarella_gpio_config(GPIO_LP5523_ENABLE, GPIO_FUNC_SW_OUTPUT);
ambarella_gpio_set(GPIO_LP5523_ENABLE, 0);
}
}
}
static struct lp5523_platform_data __initdata lp5523_data = {
.label = "lp5523",
.engine_config = &lp5523_engine_config,
.clock_mode = LP5523_CLOCK_INT,
.enable = lp5523_enable,
};
static struct lp5521_led_config lp5521_led_config[] = {
{
.chan_nr = 0,
.led_current = 255,
.max_current = 255,
}, {
.chan_nr = 1,
.led_current = 255,
.max_current = 255,
}, {
.chan_nr = 2,
.led_current = 255,
.max_current = 255,
}
};
static struct lp5521_platform_data __initdata lp5521_data = {
.label = "lp5521",
.led_config = &lp5521_led_config[0],
.num_channels = ARRAY_SIZE(lp5521_led_config),
.clock_mode = LP5521_CLOCK_INT,
};
static struct i2c_board_info __initdata quartz_i2c_devices[] = {
{
I2C_BOARD_INFO("lp5523", 0x33),
.platform_data = &lp5523_data,
},
{
I2C_BOARD_INFO("lp5521", 0x35),
.platform_data = &lp5521_data,
},
};
/* ==========================================================================*/
void init_dropcam_quartz(void)
{
int i;
ambarella_init_machine("Dropcam");
printk("Initializing Quartz Dropcam board (revision %d)\n", AMBARELLA_BOARD_REV(system_rev));
/* Config Board */
ambarella_board_generic.power_detect.irq_gpio = GPIO(11);
ambarella_board_generic.power_detect.irq_line = gpio_to_irq(11);
ambarella_board_generic.power_detect.irq_type = IRQF_TRIGGER_FALLING;
ambarella_board_generic.power_detect.irq_gpio_val = GPIO_LOW;
ambarella_board_generic.power_detect.irq_gpio_mode = GPIO_FUNC_SW_INPUT;
/* Config SD */
ambarella_platform_sd_controller0.max_clock = 25000000;
fio_default_owner = SELECT_FIO_SDIO;
ambarella_platform_sd_controller0.slot[0].cd_delay = 100;
ambarella_platform_sd_controller0.slot[0].fixed_wp = 0;
ambarella_platform_sd_controller0.slot[0].fixed_cd = 0;
ambarella_platform_sd_controller0.slot[0].gpio_cd.irq_gpio = -1;
ambarella_platform_sd_controller0.slot[0].gpio_cd.irq_line = -1;
ambarella_platform_sd_controller0.slot[0].gpio_cd.irq_type = -1;
ambarella_platform_sd_controller0.slot[0].gpio_cd.irq_gpio_val = GPIO_LOW;
ambarella_platform_sd_controller0.slot[0].gpio_cd.irq_gpio_mode = GPIO_FUNC_SW_INPUT;
ambarella_platform_sd_controller0.slot[1].cd_delay = 100;
ambarella_platform_sd_controller0.slot[1].fixed_wp = 0;
ambarella_platform_sd_controller0.slot[1].fixed_cd = 0;
ambarella_platform_sd_controller0.slot[1].gpio_cd.irq_gpio = -1;
ambarella_platform_sd_controller0.slot[1].gpio_cd.irq_line = -1;
ambarella_platform_sd_controller0.slot[1].gpio_cd.irq_type = -1;
ambarella_platform_sd_controller0.slot[1].gpio_cd.irq_gpio_val = GPIO_LOW;
ambarella_platform_sd_controller0.slot[1].gpio_cd.irq_gpio_mode = GPIO_FUNC_SW_INPUT;
ambarella_board_generic.wifi_sd_bus = 0;
ambarella_board_generic.wifi_sd_slot = 1;
ambarella_board_generic.wifi_power.gpio_id = GPIO(6);
ambarella_board_generic.wifi_power.active_level = GPIO_HIGH;
ambarella_board_generic.wifi_power.active_delay = 100;
ambarella_board_generic.vin0_power.gpio_id = GPIO(3);
ambarella_board_generic.vin0_power.active_level = GPIO_HIGH;
ambarella_board_generic.vin0_power.active_delay = 100;
ambarella_board_generic.vin0_reset.gpio_id = GPIO(2);
ambarella_board_generic.vin0_reset.active_level = GPIO_HIGH;
ambarella_board_generic.vin0_reset.active_delay = 100;
ambarella_board_generic.bt_reset.gpio_id = GPIO(42);
ambarella_board_generic.bt_reset.active_level = GPIO_HIGH;
ambarella_board_generic.bt_reset.active_delay = 100;
ambarella_board_generic.bt_power.gpio_id = GPIO(40);
ambarella_board_generic.bt_power.active_level = GPIO_HIGH;
ambarella_board_generic.bt_power.active_delay = 100;
/* At least some of these are probably temporarily set here. Just get these
pins in a known state */
/* Set GPIO1.AFSEL[1] to 1 and GPIO1.AFSEL[2] to enable UART1 and disable SSI_SLAVE
(see 164 of A5s Programmers Manual) */
ambarella_gpio_config(GPIO1_AFSEL_1, GPIO_FUNC_HW);
ambarella_gpio_config(GPIO1_AFSEL_2, GPIO_FUNC_SW_OUTPUT);
ambarella_gpio_set(GPIO1_AFSEL_2, 1);
ambarella_gpio_config(BT_RST_GPIO, GPIO_FUNC_SW_OUTPUT);
ambarella_gpio_set(BT_RST_GPIO, 1);
ambarella_gpio_config(BT_RF_DISABLE_GPIO, GPIO_FUNC_SW_OUTPUT);
ambarella_gpio_set(BT_RF_DISABLE_GPIO, 1);
ambarella_gpio_config(BT_WAKE_GPIO, GPIO_FUNC_SW_OUTPUT);
ambarella_gpio_set(BT_WAKE_GPIO, 1);
ambarella_gpio_config(BT_HOST_WAKE_GPIO, GPIO_FUNC_SW_INPUT);
ambarella_gpio_config(ZIG_EN, GPIO_FUNC_SW_INPUT);
ambarella_gpio_set(ZIG_EN, 1);
/* Register devices */
platform_add_devices(ambarella_devices, ARRAY_SIZE(ambarella_devices));
for (i = 0; i < ARRAY_SIZE(ambarella_devices); i++) {
device_set_wakeup_capable(&ambarella_devices[i]->dev, 1);
device_set_wakeup_enable(&ambarella_devices[i]->dev, 0);
}
spi_register_board_info(ambarella_spi_devices,
ARRAY_SIZE(ambarella_spi_devices));
ambarella_init_wm8974(0, 0x1A);
i2c_register_board_info(0, ambarella_board_vin_infos, ARRAY_SIZE(ambarella_board_vin_infos));
i2c_register_board_info(1, &ambarella_board_hdmi_info, 1);
if (dropcam_get_hw_rev_adc_val() > EVT_A_MIN && dropcam_get_hw_rev_adc_val() < EVT_A_MAX) {
memcpy(&lp5523_engine_config.prog_hex, &evta_lp5523_prog, evta_lp5523_prog_len-3);
lp5523_engine_config.engine1_start_addr = evta_lp5523_prog[evta_lp5523_prog_len-3],
lp5523_engine_config.engine2_start_addr = evta_lp5523_prog[evta_lp5523_prog_len-2],
lp5523_engine_config.engine3_start_addr = evta_lp5523_prog[evta_lp5523_prog_len-1],
lp5523_data.boot_mode = LP5523_MODE_NORMAL;
lp5523_data.led_config = &lp5523_led_config_evt_a[0];
lp5523_data.num_channels = ARRAY_SIZE(lp5523_led_config_evt_a);
} else {
/* Everything after EVT_A has new design */
memcpy(&lp5523_engine_config.prog_hex, &evtb_lp5523_prog, evtb_lp5523_prog_len-3);
lp5523_engine_config.engine1_start_addr = evtb_lp5523_prog[evtb_lp5523_prog_len-3],
lp5523_engine_config.engine2_start_addr = evtb_lp5523_prog[evtb_lp5523_prog_len-2],
lp5523_engine_config.engine3_start_addr = evtb_lp5523_prog[evtb_lp5523_prog_len-1],
lp5523_data.boot_mode = LP5523_MODE_OFF;
lp5523_data.led_config = &lp5523_led_config_evt_b[0];
lp5523_data.num_channels = ARRAY_SIZE(lp5523_led_config_evt_b);
}
i2c_register_board_info(0, quartz_i2c_devices, ARRAY_SIZE(quartz_i2c_devices));
platform_device_register(&ambarella_rtc0);
platform_device_register(&dropcam_board_input);
}