| /* |
| * 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 = 1; |
| 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); |
| } |