В некоторых релизах Ubuntu для модуля VAR-SOM-OM44 есть ошибка, из-за которой часы реального времени (RTC) не идут.
Релизы, где проявляется проблема:
Ошибка в коде инициализации GPIO.
На сборке Android такой проблемы нет. Часы идут исправно.
Ошибка в настоящий момент устранена и попадет в следующий релиз, который запланирован к выпуску на конец декабря 2012.
Для оперативного решения проблемы можно воспользоваться патчем (см. ниже).
Команда чтения даты/времени из аппаратных часов:
hwclock -r
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index d8ce26a..8a46526 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -369,6 +369,15 @@ config MACH_OMAP4_PANDA select REGULATOR_FIXED_VOLTAGE if REGULATOR select OMAP_TPS6236X +config MACH_OMAP4_VAR_SOM + bool "OMAP4 Variscite SOM" + default y + depends on ARCH_OMAP4 + select OMAP_PACKAGE_CBL + select OMAP_PACKAGE_CBS + select REGULATOR_FIXED_VOLTAGE if REGULATOR + select OMAP_TPS6236X + config MACH_OMAP5_SEVM bool "OMAP5 EVM board" default y diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 8cebb1f..78ab99d 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -266,6 +266,7 @@ obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o +obj-$(CONFIG_MACH_OMAP4_VAR_SOM) += board-var-som-om4460.o obj-$(CONFIG_MACH_PCM049) += board-omap4pcm049.o diff --git a/arch/arm/mach-omap2/board-var-som-om4460.c b/arch/arm/mach-omap2/board-var-som-om4460.c new file mode 100755 index 0000000..23123cd --- /dev/null +++ b/arch/arm/mach-omap2/board-var-som-om4460.c @@ -0,0 +1,970 @@ +/* + * Board support file for OMAP4430 based PandaBoard. + * + * Copyright (C) 2010 Texas Instruments + * + * Author: David Anders <x0132446@ti.com> + * + * Based on mach-omap2/board-4430sdp.c + * + * Author: Santosh Shilimkar <santosh.shilimkar@ti.com> + * + * Based on mach-omap2/board-3430sdp.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/leds.h> +#include <linux/gpio.h> +#include <linux/gpio_keys.h> +#include <linux/usb/otg.h> +#include <linux/hwspinlock.h> +#include <linux/i2c/twl.h> +#include <linux/spi/spi.h> +#include <linux/mfd/twl6040.h> +#include <linux/hwspinlock.h> +#include <linux/mfd/twl6040.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/fixed.h> +#include <linux/i2c/tsc2004.h> +#include <linux/wl12xx.h> +#include <linux/platform_data/omap-abe-twl6040.h> +#include <linux/ti_wilink_st.h> + +#include <mach/hardware.h> +#include <asm/hardware/gic.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <video/omapdss.h> + +#include <plat/board.h> +#include <plat/dma-44xx.h> +#include <plat/rpmsg_resmgr.h> +#include "common.h" +#include <plat/usb.h> +#include <plat/mmc.h> +#include <plat/remoteproc.h> +#include <video/omap-panel-generic-dpi.h> + +#include "hsmmc.h" +#include "control.h" +#include "mux.h" +#include "common-board-devices.h" +#include "pm.h" + +#define OMAP4_VAR_SOM_BACKLIGHT_EN_GPIO 122 +#define VAR_SOM_OM44_GPIO_AUD_PWRON 182 +#define GPIO_TSC2004_IRQ 101 +#define GPIO_TSC2004_IRQ 101 +#define GPIO_TSC_CTW_IRQ 174 +#define GPIO_TSC2004_RESET 102 + +#define GPIO_HUB_POWER 1 +#define GPIO_HUB_NRESET 62 +#define GPIO_WIFI_PMENA 43 +#define GPIO_WIFI_IRQ 41 +#define GPIO_AUDPWRON 127 +#define HDMI_GPIO_HPD 63 /* Hotplug detect */ +#define TPS62361_GPIO 7 + +#define ETH_KS8851_IRQ 171 +#define VAR_SOM_OM44_PHY_RESET 177 +#define VAR_DVK_OM44_USB_HUB_RESET 113 +#define VAR_SOM_OM44_GBIT_ETH_RESETn 0 +static int +panda_kim_suspend(struct platform_device *pdev, pm_message_t msg) +{ + return 0; +} + +static int +panda_kim_resume(struct platform_device *pdev) +{ + return 0; +} + +struct ti_st_plat_data var_som_om4460_bt_platform_data = { + .nshutdown_gpio = 42, + .dev_name = "/dev/ttyO1", + .flow_cntrl = 1, + .baud_rate = 3000000, + .suspend = panda_kim_suspend, + .resume = panda_kim_resume, + +}; + +static struct platform_device wl1271_device = { + .name = "kim", + .id = -1, + .dev = { + .platform_data = &var_som_om4460_bt_platform_data, + }, +}; +static struct omap_abe_twl6040_data var_som_om4460_abe_audio_data = { + /* Audio out */ + .has_hs = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT, + /* HandsFree through expasion connector */ + .has_hf = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT, + /* var_som_om4460Board: FM TX, var_som_om4460BoardES: can be connected to audio out */ + .has_aux = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT, + /* var_som_om4460Board: FM RX, var_som_om4460BoardES: audio in */ + .has_afm = ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT, + .has_abe = 1, + /* No jack detection. */ + .jack_detection = 0, + /* MCLK input is 38.4MHz */ + .mclk_freq = 38400000, + +}; + +static struct platform_device var_som_om4460_abe_audio = { + .name = "omap-abe-twl6040", + .id = -1, + .dev = { + .platform_data = &var_som_om4460_abe_audio_data, + }, +}; + +static struct platform_device var_som_om4460_hdmi_audio_codec = { + .name = "hdmi-audio-codec", + .id = -1, +}; + + +static struct platform_device btwilink_device = { + .name = "btwilink", + .id = -1, +}; +static struct platform_device *var_som_om4460_devices[] __initdata = { + &wl1271_device, + &var_som_om4460_abe_audio, + &var_som_om4460_hdmi_audio_codec, +// &btwilink_device, +}; + +#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE) +static struct spi_board_info var_som_om44_spi_board_info[] __initdata = { + { + .modalias = "ks8851", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 24000000, + .irq = ETH_KS8851_IRQ, + }, +}; + +static struct gpio var_som_om44_eth_gpios[] __initdata = { + { ETH_KS8851_IRQ, GPIOF_IN, "eth_irq" }, +}; + +static int __init var_som_ks8851_init(void) +{ + int status; + + /* Request of GPIO lines */ + status = gpio_request_array(var_som_om44_eth_gpios, + ARRAY_SIZE(var_som_om44_eth_gpios)); + if (status) + pr_err("Cannot request ETH GPIOs\n"); + + return status; +} +#endif + +static const struct usbhs_omap_board_data usbhs_bdata __initconst = { + .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, + .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED, + .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED, + .phy_reset = false, + .reset_gpio_port[0] = -EINVAL, + .reset_gpio_port[1] = -EINVAL, + .reset_gpio_port[2] = -EINVAL, + .clock_name = "auxclk3_ck", + .clock_rate = 19200000, +}; + + + +static void __init omap4_ehci_init(void) +{ + struct clk *phy_ref_clk; + int error; + unsigned long * addr; + + /* USB PHY Reset */ + omap_mux_init_gpio(VAR_SOM_OM44_PHY_RESET, OMAP_PIN_OUTPUT); + + error = gpio_request(VAR_SOM_OM44_PHY_RESET, "VAR_SOM_OM44_PHY_RESET"); + if (error < 0) { + pr_err("%s:failed to request GPIO %d, error %d\n", + __func__, VAR_SOM_OM44_PHY_RESET, error); + return; + } + + error = gpio_direction_output(VAR_SOM_OM44_PHY_RESET , 0); + if (error < 0) { + pr_err("%s: GPIO configuration failed: GPIO %d,error %d\n", + __func__, VAR_SOM_OM44_PHY_RESET, error); + gpio_free(VAR_SOM_OM44_PHY_RESET); + } + + + /* DVK USB HUB Reset */ + omap_mux_init_gpio(VAR_DVK_OM44_USB_HUB_RESET, OMAP_PIN_OUTPUT); + + error = gpio_request(VAR_DVK_OM44_USB_HUB_RESET, "VAR_DVK_OM44_USB_HUB_RESET"); + if (error < 0) { + pr_err("%s:failed to request GPIO %d, error %d\n", + __func__, VAR_DVK_OM44_USB_HUB_RESET, error); + return; + } + + error = gpio_direction_output(VAR_DVK_OM44_USB_HUB_RESET , 0); + if (error < 0) { + pr_err("%s: GPIO configuration failed: GPIO %d,error %d\n", + __func__, VAR_DVK_OM44_USB_HUB_RESET, error); + gpio_free(VAR_DVK_OM44_USB_HUB_RESET); + } + + // VAR-SOM-OM44 USB HUB reset off + omap_mux_init_signal("sim_clk.gpio_wk1", OMAP_MUX_MODE0 |OMAP_PIN_OUTPUT); + + // VAR-SOM-OM44 Gbit ethernet controller reset off + omap_mux_init_signal("sim_io.gpio_wk0", OMAP_MUX_MODE3 |OMAP_PIN_OUTPUT); + + + addr=(unsigned long *)ioremap(0x4a100600,4); // PBIAS Control Register + *(unsigned long* )addr = 0x1d700000; // Set VDDS voltage + + addr=(unsigned long *)ioremap(0x4A31E600,4); + *(unsigned long* )addr = 0x10000000;//Notify VDDS stable, disable strong pull down + + addr=(unsigned long *)ioremap(0x4A31E040,4); + *(unsigned long* )addr = 0x7000b;//GPIOWK pads I/O control. Set wk0 as gpio + + error = gpio_request(1, "VAR_SOM_OM44_GBIT_ETH_RESETn"); + if (error < 0) { + pr_err("%s:failed to request GPIO %d, error %d\n", + __func__, VAR_SOM_OM44_GBIT_ETH_RESETn, error); + return; + } + + gpio_direction_output(VAR_SOM_OM44_GBIT_ETH_RESETn , 1); + + /* FREF_CLK3 provides the 19.2 MHz reference clock to the PHY */ + phy_ref_clk = clk_get(NULL, "auxclk3_ck"); + if (IS_ERR(phy_ref_clk)) { + pr_err("Cannot request auxclk3\n"); + goto error1; + } + clk_set_rate(phy_ref_clk, 19200000); + clk_enable(phy_ref_clk); + mdelay(20); + + // VAR-SOM-OM44 Phy reset de-assert + gpio_set_value(VAR_SOM_OM44_PHY_RESET, 1); + + usbhs_init(&usbhs_bdata); + mdelay(20); + + + // VAR-SOM-OM44 USB HUB reset de-assert + omap_mux_init_signal("sim_clk.gpio_wk1", OMAP_MUX_MODE3 |OMAP_PIN_INPUT); + + mdelay(20); + + // DVK USB HUB de-assert + gpio_set_value(VAR_DVK_OM44_USB_HUB_RESET, 1); + + return; +error1: + pr_err("Unable to initialize EHCI power/reset\n"); + return; +} + +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_UTMI, + .mode = MUSB_OTG, + .power = 100, +}; + +static struct omap2_hsmmc_info mmc[] = { + { + .mmc = 1, + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, + .gpio_wp = -EINVAL, + .gpio_cd = -EINVAL, + }, + { + .mmc = 5, + .caps = MMC_CAP_4_BIT_DATA /*| MMC_CAP_POWER_OFF_CARD*/, + .gpio_cd = 110, + .gpio_wp = -EINVAL, + .ocr_mask = MMC_VDD_32_33, + .power_saving = false, + }, + { + .name = "wl1271", + .mmc = 4, + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD, + .gpio_wp = -EINVAL, + .gpio_cd = -EINVAL, + .ocr_mask = MMC_VDD_165_195, + .nonremovable = true, + }, + {} /* Terminator */ +}; + +static struct regulator_consumer_supply omap4_panda_vmmc4_supply[] = { + REGULATOR_SUPPLY("vmmc", "omap_hsmmc.3"), +}; + +static struct regulator_init_data panda_vmmc4 = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(omap4_panda_vmmc4_supply), + .consumer_supplies = omap4_panda_vmmc4_supply, +}; + +static struct fixed_voltage_config panda_vwlan = { + .supply_name = "vwl1271", + .microvolts = 1800000, /* 1.8V */ + .gpio = GPIO_WIFI_PMENA, + .startup_delay = 70000, /* 70msec */ + .enable_high = 1, + .enabled_at_boot = 0, + .init_data = &panda_vmmc4, +}; + +static struct platform_device omap_vwlan_device = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &panda_vwlan, + }, +}; + +struct wl12xx_platform_data omap_var_som_om4460_wlan_data __initdata = { + /* PANDA ref clock is .4 MHz */ + .board_ref_clock = 2, +}; + +static struct omap_rprm_regulator sdp4430_rprm_regulators[] = { + { + .name = "cam2pwr", + }, +}; + +static struct regulator_consumer_supply sdp4430_cam2_supply[] = { + { + .supply = "cam2pwr", + }, +}; + +static struct regulator_init_data sdp4430_vaux3 = { + .constraints = { + .min_uV = 1000000, + .max_uV = 3000000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = sdp4430_cam2_supply, +}; + +static int omap4_twl6030_hsmmc_late_init(struct device *dev) +{ + int irq = 0; + struct platform_device *pdev = container_of(dev, + struct platform_device, dev); + struct omap_mmc_platform_data *pdata = dev->platform_data; + + if (!pdata) { + dev_err(dev, "%s: NULL platform data\n", __func__); + return -EINVAL; + } + /* Setting MMC1 Card detect Irq */ + if (pdev->id == 0) { + irq = twl6030_mmc_card_detect_config(); + if (irq < 0) { + dev_err(dev, "%s: Error card detect config(%d)\n", + __func__, irq); + return irq; + } + pdata->slots[0].card_detect = twl6030_mmc_card_detect; + } + return 0; +} + +static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev) +{ + struct omap_mmc_platform_data *pdata; + + /* dev can be null if CONFIG_MMC_OMAP_HS is not set */ + if (!dev) { + pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n"); + return; + } + pdata = dev->platform_data; + + pdata->init = omap4_twl6030_hsmmc_late_init; +} + +static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers) +{ + struct omap2_hsmmc_info *c; + + omap_hsmmc_init(controllers); + for (c = controllers; c->mmc; c++) + omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev); + + return 0; +} + +static struct twl6040_codec_data twl6040_codec = { + /* single-step ramp for headset and handsfree */ + .hs_left_step = 0x0f, + .hs_right_step = 0x0f, + .hf_left_step = 0x1d, + .hf_right_step = 0x1d, +}; + +static struct twl6040_platform_data twl6040_data = { + .codec = &twl6040_codec, + .audpwron_gpio = VAR_SOM_OM44_GPIO_AUD_PWRON, + .irq_base = TWL6040_CODEC_IRQ_BASE, +}; + +/* var_som_om4460 board uses the common PMIC configuration */ +static struct twl4030_platform_data omap4_var_som_om4460_twldata = { + /* Regulators */ + .vaux3 = &sdp4430_vaux3, +}; +#ifndef CONFIG_TOUCHSCREEN_CTW6120 +/* + * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM + * is connected as I2C slave device, and can be accessed at address 0x50 + */ +static int tsc2004_init_irq(void) +{ + int ret = 0; + + ret = gpio_request(GPIO_TSC2004_IRQ, "tsc2004-irq"); + if (ret < 0) { + pr_err("%s: failed to request GPIO#%d: %d\n", + __func__, GPIO_TSC2004_IRQ, ret); + return ret; + } + + if (gpio_direction_input(GPIO_TSC2004_IRQ)) { + pr_err("%s: GPIO#%d cannot be configured as input\n", + __func__, GPIO_TSC2004_IRQ); + return -ENXIO; + } + + ret = gpio_request(GPIO_TSC2004_RESET, "tsc2004-reset"); + if (ret < 0) { + pr_err("%s: failed to request GPIO#%d: %d\n", + __func__, GPIO_TSC2004_RESET, ret); + return ret; + } + + if (gpio_direction_output(GPIO_TSC2004_RESET, 1)) { + pr_err("%s: GPIO#%d cannot be configured as output 1\n", + __func__, GPIO_TSC2004_RESET); + return -ENXIO; + } + + /* FIXME: meantime do not need debounce. */ + //omap_set_gpio_debounce(GPIO_TSC2004_IRQ, 1); + //omap_set_gpio_debounce_time(GPIO_TSC2004_IRQ, 0xa); + return ret; +} + +static void tsc2004_exit_irq(void) +{ + gpio_free(GPIO_TSC2004_IRQ); +} + +static int tsc2004_get_irq_level(void) +{ + return gpio_get_value(GPIO_TSC2004_IRQ) ? 0 : 1; +} +struct tsc2004_platform_data VAR_SOM_OM4460_tsc2004data = { + .model = 2004, + .x_plate_ohms = 180, + .get_pendown_state = tsc2004_get_irq_level, + .init_platform_hw = tsc2004_init_irq, + .exit_platform_hw = tsc2004_exit_irq, +}; + +#else +static int tsc_ctw6120_init_irq(void) +{ + int ret = 0; + ret = gpio_request(GPIO_TSC_CTW_IRQ, "GPIO_TSC_CTW_IRQ-irq"); + if (ret < 0) { + pr_err("%s: failed to request GPIO#%d: %d\n", + __func__, GPIO_TSC_CTW_IRQ, ret); + return ret; + } + + if (gpio_direction_input(GPIO_TSC_CTW_IRQ)) { + pr_err("%s: GPIO#%d cannot be configured as input\n", + __func__, GPIO_TSC_CTW_IRQ); + return -ENXIO; + } + + return ret; +} +#endif + + + +static struct omap_i2c_bus_board_data __initdata var_som_om4460_i2c_1_bus_pdata; +static struct omap_i2c_bus_board_data __initdata var_som_om4460_i2c_2_bus_pdata; +static struct omap_i2c_bus_board_data __initdata var_som_om4460_i2c_3_bus_pdata; +static struct omap_i2c_bus_board_data __initdata var_som_om4460_i2c_4_bus_pdata; + + + +static void __init omap_i2c_hwspinlock_init(int bus_id, int spinlock_id, + struct omap_i2c_bus_board_data *pdata) +{ + /* spinlock_id should be -1 for a generic lock request */ + if (spinlock_id < 0) + pdata->handle = hwspin_lock_request(); + else + pdata->handle = hwspin_lock_request_specific(spinlock_id); + + if (pdata->handle != NULL) { + pdata->hwspin_lock_timeout = hwspin_lock_timeout; + pdata->hwspin_unlock = hwspin_unlock; + } else { + pr_err("I2C hwspinlock request failed for bus %d\n", bus_id); + } +} + +static struct i2c_board_info __initdata var_som_om44_i2c_3_boardinfo[] = { +#ifndef CONFIG_TOUCHSCREEN_CTW6120 + { + I2C_BOARD_INFO("tsc2004", 0x48), + .type = "tsc2004", + .platform_data = &VAR_SOM_OM4460_tsc2004data, + }, +#endif +#ifdef CONFIG_TOUCHSCREEN_CTW6120 + { + I2C_BOARD_INFO("ctw6120", 0x38), + .flags = I2C_CLIENT_WAKE, + .irq = OMAP_GPIO_IRQ(GPIO_TSC_CTW_IRQ), + }, +#endif +}; +static int __init omap4_var_som_om4460_i2c_init(void) +{ + int error; + omap_i2c_hwspinlock_init(1, 0, &var_som_om4460_i2c_1_bus_pdata); + omap_i2c_hwspinlock_init(3, 2, &var_som_om4460_i2c_3_bus_pdata); + omap_i2c_hwspinlock_init(4, 3, &var_som_om4460_i2c_4_bus_pdata); + + omap_register_i2c_bus_board_data(1, &var_som_om4460_i2c_1_bus_pdata); + omap_register_i2c_bus_board_data(3, &var_som_om4460_i2c_3_bus_pdata); + omap_register_i2c_bus_board_data(4, &var_som_om4460_i2c_4_bus_pdata); + + omap4_pmic_get_config(&omap4_var_som_om4460_twldata, TWL_COMMON_PDATA_USB, + TWL_COMMON_REGULATOR_VDAC | + TWL_COMMON_REGULATOR_VAUX2 | + TWL_COMMON_REGULATOR_VMMC | + TWL_COMMON_REGULATOR_VPP | + TWL_COMMON_REGULATOR_VANA | + TWL_COMMON_REGULATOR_VCXIO | + TWL_COMMON_REGULATOR_VUSB | + TWL_COMMON_REGULATOR_CLK32KG | + TWL_COMMON_REGULATOR_V1V8 | + TWL_COMMON_REGULATOR_V2V1); + omap4_pmic_init("twl6030", &omap4_var_som_om4460_twldata, + &twl6040_data, OMAP44XX_IRQ_SYS_2N); +#ifndef CONFIG_TOUCHSCREEN_CTW6120 + var_som_om44_i2c_3_boardinfo[0].irq = gpio_to_irq(GPIO_TSC2004_IRQ); +#endif + omap_register_i2c_bus(3, 400, var_som_om44_i2c_3_boardinfo, ARRAY_SIZE(var_som_om44_i2c_3_boardinfo)); + + omap_register_i2c_bus(4, 400, NULL, 0); + + /* + * Drive MSECURE high for TWL6030 write access. + */ +#if 1 + + /* Msecure */ + error = omap_mux_init_signal("fref_clk0_out.gpio_wk6", OMAP_PIN_OUTPUT); + if (error < 0) + pr_err("Failed to configure fref_clk0_out.gpio_wk6\n"); + + gpio_request(TWL6030_MSECURE_GPIO, "msecure"); + gpio_direction_output(TWL6030_MSECURE_GPIO, 1); + gpio_export(TWL6030_MSECURE_GPIO, 1); + gpio_set_value(TWL6030_MSECURE_GPIO, 1); + +#endif + return 0; + +} + +#ifdef CONFIG_OMAP_MUX +static struct omap_board_mux board_mux[] __initdata = { + /* dispc2_data23 */ + OMAP4_MUX(USBB2_ULPITLL_STP, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data22 */ + OMAP4_MUX(USBB2_ULPITLL_DIR, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data21 */ + OMAP4_MUX(USBB2_ULPITLL_NXT, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data20 */ + OMAP4_MUX(USBB2_ULPITLL_DAT0, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data19 */ + OMAP4_MUX(USBB2_ULPITLL_DAT1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data18 */ + OMAP4_MUX(USBB2_ULPITLL_DAT2, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data15 */ + OMAP4_MUX(USBB2_ULPITLL_DAT3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data14 */ + OMAP4_MUX(USBB2_ULPITLL_DAT4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data13 */ + OMAP4_MUX(USBB2_ULPITLL_DAT5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data12 */ + OMAP4_MUX(USBB2_ULPITLL_DAT6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data11 */ + OMAP4_MUX(USBB2_ULPITLL_DAT7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data10 */ + OMAP4_MUX(DPM_EMU3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data9 */ + OMAP4_MUX(DPM_EMU4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data16 */ + OMAP4_MUX(DPM_EMU5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data17 */ + OMAP4_MUX(DPM_EMU6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_hsync */ + OMAP4_MUX(DPM_EMU7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_pclk */ + OMAP4_MUX(DPM_EMU8, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_vsync */ + OMAP4_MUX(DPM_EMU9, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_de */ + OMAP4_MUX(DPM_EMU10, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data8 */ + OMAP4_MUX(DPM_EMU11, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data7 */ + OMAP4_MUX(DPM_EMU12, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data6 */ + OMAP4_MUX(DPM_EMU13, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data5 */ + OMAP4_MUX(DPM_EMU14, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data4 */ + OMAP4_MUX(DPM_EMU15, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data3 */ + OMAP4_MUX(DPM_EMU16, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data2 */ + OMAP4_MUX(DPM_EMU17, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data1 */ + OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data0 */ + OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* TSC IRQ; input; GPIO 101 */ + OMAP4_MUX(GPMC_NCS4, OMAP_PIN_INPUT | OMAP_MUX_MODE3), + /* TSC reset; output = 1; GPIO 102 */ + OMAP4_MUX(GPMC_NCS5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3), +#ifdef CONFIG_TOUCHSCREEN_CTW6120 + /* TSC CTW IRQ; input; GPIO 174 */ + OMAP4_MUX(KPD_COL0, OMAP_PIN_INPUT | OMAP_MUX_MODE3), +#endif + /* Audio ON GPIO 182 */ + OMAP4_MUX(FREF_CLK2_OUT, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3), + + /* GPIO 133, VAR-DVK-44 USB HUB Reset */ + OMAP4_MUX(ABE_MCBSP2_FSX, OMAP_MUX_MODE3| OMAP_PIN_OUTPUT), + + /* GPIO 171, KS8851 ETH IRQ */ + OMAP4_MUX(KPD_COL3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), + + /* Backlight Enabled */ + OMAP4_MUX(ABE_DMIC_DIN3, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT), + + /* SD-MMC5, VAR-DVK-44 SD Card slot */ + OMAP4_MUX(SDMMC5_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(SDMMC5_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(SDMMC5_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(ABE_DMIC_DIN3, OMAP_MUX_MODE3| OMAP_PIN_OUTPUT), + + /* GPIO 110, SD-MMC5 CD */ + OMAP4_MUX(ABE_MCBSP2_CLKX, OMAP_MUX_MODE3| OMAP_PIN_INPUT), + + OMAP4_MUX(MCSPI4_CLK, OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(MCSPI4_SIMO, OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(MCSPI4_SOMI, OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(UART4_TX, OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(UART4_RX, OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(MCSPI4_CS0, OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP), + + /* WLAN_EN - GPIO 42 */ + OMAP4_MUX(GPMC_A18, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT), + /* WLAN IRQ - GPIO 41 */ + OMAP4_MUX(GPMC_A17, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP), + + OMAP4_MUX(I2C3_SDA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), /* I2C3 SDA */ + OMAP4_MUX(I2C3_SCL, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), /* I2C3 SCL */ + + OMAP4_MUX(I2C4_SDA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), /* I2C4 SDA */ + OMAP4_MUX(I2C4_SCL, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), /* I2C4 SCL */ + + OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT), + OMAP4_MUX(I2C2_SDA, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT), /* UART1 TX */ + OMAP4_MUX(I2C2_SCL, OMAP_MUX_MODE1 | OMAP_PIN_INPUT), /* UART1 RX */ + OMAP4_MUX(MCSPI1_CS2, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),/* UART1 CTS */ + OMAP4_MUX(MCSPI1_CS3, OMAP_MUX_MODE1 | OMAP_PIN_INPUT), /* UART1 RTS */ + { .reg_offset = OMAP_MUX_TERMINATOR }, + +}; + +#else +#define board_mux NULL +#endif + + +static int var_som_om44_enable_lcd(struct omap_dss_device *dssdev) +{ + gpio_set_value(dssdev->reset_gpio, 1); + return 0; +} + +static void var_som_om44_disable_lcd(struct omap_dss_device *dssdev) +{ + gpio_set_value(dssdev->reset_gpio, 0); + +} +/* Using generic display panel */ +static struct panel_generic_dpi_data omap4_dvi_panel = { +#ifdef CONFIG_TOUCHSCREEN_CTW6120 + .name = "ETM_070001ADH6", +#else + .name = "URT_UMSH_8423MD_T", +#endif + .platform_enable = var_som_om44_enable_lcd, + .platform_disable = var_som_om44_disable_lcd, +}; + +struct omap_dss_device omap4_var_som_om44_lcd_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "dvi", + .driver_name = "generic_dpi_panel", + .data = &omap4_dvi_panel, + .phy.dpi.data_lines = 24, + .reset_gpio = OMAP4_VAR_SOM_BACKLIGHT_EN_GPIO, + .channel = OMAP_DSS_CHANNEL_LCD2, +}; + + + +static struct gpio var_som_om4460_hdmi_gpios_hpd[] = { + { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" }, +}; + +static int omap4_var_som_om4460_panel_enable_hdmi(struct omap_dss_device *dssdev) +{ + + + return 0; +} + +static void omap4_var_som_om4460_panel_disable_hdmi(struct omap_dss_device *dssdev) +{ +} + +static struct omap_dss_hdmi_data omap4_var_som_om4460_hdmi_data = { + .hpd_gpio = HDMI_GPIO_HPD, +}; + +static struct omap_dss_device omap4_var_som_om4460_hdmi_device = { + .name = "hdmi", + .driver_name = "hdmi_panel", + .type = OMAP_DISPLAY_TYPE_HDMI, + .platform_enable = omap4_var_som_om4460_panel_enable_hdmi, + .platform_disable = omap4_var_som_om4460_panel_disable_hdmi, + .channel = OMAP_DSS_CHANNEL_DIGIT, + .data = &omap4_var_som_om4460_hdmi_data, +}; + +static struct omap_dss_device *omap4_var_som_om4460_dss_devices[] = { + &omap4_var_som_om44_lcd_device, + &omap4_var_som_om4460_hdmi_device, +}; + +static struct omap_dss_board_info omap4_var_som_om4460_dss_data = { + .num_devices = ARRAY_SIZE(omap4_var_som_om4460_dss_devices), + .devices = omap4_var_som_om4460_dss_devices, + .default_device = &omap4_var_som_om44_lcd_device, +}; + +/* + * These device paths represent the onboard USB <-> Ethernet bridge, and + * the WLAN module on var_som_om4460, both of which need their random or all-zeros + * mac address replacing with a per-cpu stable generated one + */ +static const char * const var_som_om4460_fixup_mac_device_paths[] = { + "usb1/1-1/1-1.1/1-1.1:1.0", + "wl12xx", +}; + +void __init omap4_var_som_om4460_display_init(void) +{ + gpio_request_array(var_som_om4460_hdmi_gpios_hpd, ARRAY_SIZE(var_som_om4460_hdmi_gpios_hpd)); + omap_display_init(&omap4_var_som_om4460_dss_data); + /* + * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and + * later have external pull up on the HDMI I2C lines + */ + if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2) + omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP); + else + omap_hdmi_init(0); + + + omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN); + + gpio_direction_output(OMAP4_VAR_SOM_BACKLIGHT_EN_GPIO , 0); + +} + +#define GPIO_CAM_GLOBAL_POWER 83 +#define GPIO_CAM1_RESET 3 +#define GPIO_CAM2_RESET 175 + +static void var_som_om44_camera_init(void) +{ + omap_mux_init_gpio(GPIO_CAM_GLOBAL_POWER, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(GPIO_CAM1_RESET, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(GPIO_CAM2_RESET, OMAP_PIN_OUTPUT); +} + +static void __init enable_board_wakeups(void) +{ +return; + /* user button on GPIO_121 */ + omap_mux_init_signal("gpio_121", + OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP); + + /* sys_nirq1 for TWL6030 (USB, PMIC, etc) */ + omap_mux_init_signal("sys_nirq1", + OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP); +} + +static void omap4_var_som_om4460_init_rev(void) +{ + var_som_om4460_abe_audio_data.card_name = "PandaES"; +} + + +static void __init omap4_var_som_om4460_init(void) +{ + int package = OMAP_PACKAGE_CBS; + int ret; + int status; + + if (omap_rev() == OMAP4430_REV_ES1_0) + package = OMAP_PACKAGE_CBL; + + omap4_mux_init(board_mux, NULL, package); + + omap_var_som_om4460_wlan_data.irq = gpio_to_irq(GPIO_WIFI_IRQ); + + omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE); + omap_mux_init_gpio(GPIO_WIFI_PMENA, OMAP_PIN_OUTPUT); + + omap_register_mac_device_fixup_paths(var_som_om4460_fixup_mac_device_paths, + ARRAY_SIZE(var_som_om4460_fixup_mac_device_paths)); + ret = wl12xx_set_platform_data(&omap_var_som_om4460_wlan_data); + if (ret) + pr_err("error setting wl12xx data: %d\n", ret); + omap4_var_som_om4460_init_rev(); + omap4_var_som_om4460_i2c_init(); + platform_add_devices(var_som_om4460_devices, ARRAY_SIZE(var_som_om4460_devices)); + platform_device_register(&omap_vwlan_device); + + omap_serial_init(); + omap4_twl6030_hsmmc_init(mmc); + omap4_ehci_init(); + usb_musb_init(&musb_board_data); +#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE) + status = var_som_ks8851_init(); + if (status) { + pr_err("Ethernet initialization failed: %d\n", status); + } else { + var_som_om44_spi_board_info[0].irq = gpio_to_irq(ETH_KS8851_IRQ); + spi_register_board_info(var_som_om44_spi_board_info, + ARRAY_SIZE(var_som_om44_spi_board_info)); + } +#endif + omap4_var_som_om4460_display_init(); + if (cpu_is_omap446x()) { + /* Vsel0 = gpio, vsel1 = gnd */ + ret = omap_tps6236x_board_setup(true, TPS62361_GPIO, -1, + OMAP_PIN_OFF_OUTPUT_HIGH, -1); + if (ret) + pr_err("TPS62361 initialization failed: %d\n", ret); + } + +#ifdef CONFIG_TOUCHSCREEN_CTW6120 + tsc_ctw6120_init_irq(); +#endif + var_som_om44_camera_init(); + omap_enable_smartreflex_on_init(); + omap_rprm_regulator_init(sdp4430_rprm_regulators, + ARRAY_SIZE(sdp4430_rprm_regulators)); + enable_board_wakeups(); +} + +static void __init omap4_var_som_om4460_map_io(void) +{ + omap2_set_globals_443x(); + omap44xx_map_common_io(); +} + +static const char *omap4_var_som_om4460_match[] = { + "ti,omap4-var_som_om4460", + NULL, +}; +static void __init omap4_var_som_om4460_reserve(void) +{ + omap_rproc_reserve_cma(RPROC_CMA_OMAP4); + omap_reserve(); +} + +MACHINE_START(VAR_SOM_OM4460, "var_som_om4460") + /* Maintainer: David Anders - Texas Instruments Inc */ + .atag_offset = 0x100, + .reserve = omap4_var_som_om4460_reserve, + .map_io = omap4_var_som_om4460_map_io, + .init_early = omap4430_init_early, + .init_irq = gic_init_irq, + .handle_irq = gic_handle_irq, + .init_machine = omap4_var_som_om4460_init, + .timer = &omap4_timer, + .restart = omap_prcm_restart, + .dt_compat = omap4_var_som_om4460_match, +MACHINE_END diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 4df10fa..0d98d1f 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -224,9 +224,6 @@ void __init omap4xxx_check_features(void) read_tap_reg(OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1); switch ((si_type & (3 << 16)) >> 16) { case 2: - /* High performance device */ - omap_features |= OMAP4_HAS_MPU_1_5GHZ; - break; case 1: default: /* Standard device */ diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index d8693cb..b46e38d 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -228,19 +228,6 @@ static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = { }, }; -static struct omap_device_pad default_omap4_uart4_pads[] __initdata = { - { - .name = "uart4_tx.uart4_tx", - .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, - }, - { - .name = "uart4_rx.uart4_rx", - .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, - .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0, - .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0, - }, -}; - static void omap_serial_fill_default_pads(struct omap_board_data *bdata) { switch (bdata->id) { @@ -256,17 +243,6 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata) bdata->pads = default_uart3_pads; bdata->pads_cnt = ARRAY_SIZE(default_uart3_pads); break; - case 3: - if (cpu_is_omap44xx() || cpu_is_omap54xx()) { - bdata->pads = default_omap4_uart4_pads; - bdata->pads_cnt = - ARRAY_SIZE(default_omap4_uart4_pads); - } else if (cpu_is_omap3630()) { - bdata->pads = default_omap36xx_uart4_pads; - bdata->pads_cnt = - ARRAY_SIZE(default_omap36xx_uart4_pads); - } - break; default: break; } diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index f9c9f33..75c00b1 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -1169,3 +1169,4 @@ elite_ulk MACH_ELITE_ULK ELITE_ULK 3888 pov2 MACH_POV2 POV2 3889 ipod_touch_2g MACH_IPOD_TOUCH_2G IPOD_TOUCH_2G 3890 da850_pqab MACH_DA850_PQAB DA850_PQAB 3891 +var_som_om4460 MACH_VAR_SOM_OM4460 VAR_SOM_OM4460 3939 \ No newline at end of file diff --git a/debian.ti-omap4/changelog b/debian.ti-omap4/changelog index 65e3302..8de210d 100644 --- a/debian.ti-omap4/changelog +++ b/debian.ti-omap4/changelog @@ -1,4 +1,4 @@ -linux-ti-omap4 (3.4.0-1487.6) precise; urgency=low +linux-ti-omap4 (3.4.0-1487.6+var15) precise; urgency=low [ Xavier Boudet ] diff --git a/debian.ti-omap4/config/config.common.ubuntu b/debian.ti-omap4/config/config.common.ubuntu index ae49e7e..360c354 100644 --- a/debian.ti-omap4/config/config.common.ubuntu +++ b/debian.ti-omap4/config/config.common.ubuntu @@ -967,7 +967,7 @@ CONFIG_ECONET=m CONFIG_ECONET_AUNUDP=y CONFIG_ECONET_NATIVE=y CONFIG_ECRYPT_FS=y -CONFIG_EEPROM_93CX6=m +CONFIG_EEPROM_93CX6=y # CONFIG_EEPROM_93XX46 is not set CONFIG_EEPROM_AT24=m CONFIG_EEPROM_AT25=m @@ -1788,9 +1788,9 @@ CONFIG_KPROBES=y # CONFIG_KPROBES_SANITY_TEST is not set CONFIG_KPROBE_EVENT=y CONFIG_KRETPROBES=y -CONFIG_KS8842=m -CONFIG_KS8851=m -CONFIG_KS8851_MLL=m +CONFIG_KS8842=y +CONFIG_KS8851=y +CONFIG_KS8851_MLL=y CONFIG_KS959_DONGLE=m CONFIG_KSDAZZLE_DONGLE=m CONFIG_KSM=y @@ -1944,6 +1944,7 @@ CONFIG_MAC80211_RC_PID=y # CONFIG_MAC80211_VERBOSE_PS_DEBUG is not set # CONFIG_MAC80211_VERBOSE_TDLS_DEBUG is not set CONFIG_MACH_OMAP4_PANDA=y +CONFIG_MACH_OMAP4_VAR_SOM=y CONFIG_MACH_OMAP_4430SDP=y CONFIG_MACH_OMAP_GENERIC=y CONFIG_MACVLAN=m @@ -3547,6 +3548,7 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=m # CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set CONFIG_TOUCHSCREEN_BU21013=m CONFIG_TOUCHSCREEN_CLEARPAD_TM1217=m +# CONFIG_TOUCHSCREEN_CTW6120 is not set CONFIG_TOUCHSCREEN_CY8CTMG110=m # CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set CONFIG_TOUCHSCREEN_DA9034=m @@ -3575,6 +3577,7 @@ CONFIG_TOUCHSCREEN_TOUCHIT213=m CONFIG_TOUCHSCREEN_TOUCHRIGHT=m CONFIG_TOUCHSCREEN_TOUCHWIN=m CONFIG_TOUCHSCREEN_TPS6507X=m +CONFIG_TOUCHSCREEN_TSC2004=y CONFIG_TOUCHSCREEN_TSC2005=m CONFIG_TOUCHSCREEN_TSC2007=m # CONFIG_TOUCHSCREEN_TSC_SERIO is not set @@ -3826,7 +3829,7 @@ CONFIG_USB_NET_PLUSB=m # CONFIG_USB_NET_QMI_WWAN is not set CONFIG_USB_NET_RNDIS_HOST=m CONFIG_USB_NET_RNDIS_WLAN=m -CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC75XX=y CONFIG_USB_NET_SMSC95XX=y CONFIG_USB_NET_ZAURUS=m # CONFIG_USB_OHCI_HCD is not set diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index e93c61a..85e51b6 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -42,6 +42,19 @@ config TOUCHSCREEN_ADS7846 To compile this driver as a module, choose M here: the module will be called ads7846. +config TOUCHSCREEN_CTW6120 + tristate "CTW1620 based touchscreens" + depends on I2C + help + Say Y here if you have a touchscreen interface using the + CTW8120 controller, and your board-specific + initialization code includes that in its table of I2C devices. + + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called ctw6120. + config TOUCHSCREEN_AD7877 tristate "AD7877 based touchscreens" depends on SPI_MASTER @@ -764,6 +777,17 @@ config TOUCHSCREEN_TOUCHIT213 To compile this driver as a module, choose M here: the module will be called touchit213. +config TOUCHSCREEN_TSC2004 + tristate "TSC2004 based touchscreens" + depends on I2C + help + Say Y here if you have a TSC2004 based touchscreen. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called tsc2004. + config TOUCHSCREEN_TSC_SERIO tristate "TSC-10/25/40 serial touchscreen support" select SERIO diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 4b9a533..c79f606 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI) += synaptics_i2c_rmi.o obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o +obj-$(CONFIG_TOUCHSCREEN_TSC2004) += tsc2004.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO) += tsc40.o @@ -71,3 +72,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o obj-$(CONFIG_TOUCHSCREEN_QUANTUM_OBP) += qtouch_obp_ts.o +obj-$(CONFIG_TOUCHSCREEN_CTW6120) += ctw6120.o diff --git a/drivers/input/touchscreen/ctw6120.c b/drivers/input/touchscreen/ctw6120.c new file mode 100644 index 0000000..fb5fa93 --- /dev/null +++ b/drivers/input/touchscreen/ctw6120.c @@ -0,0 +1,381 @@ +/* + * CTW6120 based touchscreen and sensor driver + * + * Copyright (c) 2010 Variscite LTD. + * + * Using code from: + * - corgi_ts.c + * Copyright (C) 2004-2005 Richard Purdie + * - omap_ts.[hc], ctw6120.h, ts_osk.c + * Copyright (C) 2002 MontaVista Software + * Copyright (C) 2004 Texas Instruments + * Copyright (C) 2005 Dirk Behme + * + * This program is free software; you can redistribute it and/or modifys + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/module.h> +#include <linux/hwmon.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/i2c/ctw6120.h> +#include <asm/irq.h> +#include <linux/workqueue.h> + + +#define TS_POLL_DELAY (1 * 1000000) /* ns delay before the first sample */ +#define TS_POLL_PERIOD (30 * 1000000) // OrenR : change to 100 for better double click + +#define MAX_12BIT ((1 << 12) - 1) + +struct ctw6120 { + char phys[32]; + char name[32]; + + struct input_dev *input; + struct i2c_client *client; + + struct hrtimer timer; + struct work_struct work; + + spinlock_t lock; + + unsigned pendown:1; /* P: lock */ + unsigned pending:1; /* P: lock */ + unsigned irq_disabled:1; /* P: lock */ + unsigned disabled:1; +}; + +static int is_pen_down(struct device *dev) +{ + struct ctw6120 *ts = dev_get_drvdata(dev); + + return ts->pendown; +} + +static ssize_t ctw6120_pen_down_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", is_pen_down(dev)); +} + +static DEVICE_ATTR(pen_down, S_IRUGO, ctw6120_pen_down_show, NULL); + +static ssize_t ctw6120_disable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ctw6120 *ts = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ts->disabled); +} + +static ssize_t ctw6120_disable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ctw6120 *ts = dev_get_drvdata(dev); + unsigned long i; + + if (strict_strtoul(buf, 10, &i)) + return -EINVAL; + + spin_lock_irq(&ts->lock); + + if (i) { + ts->disabled = 1; + ts->irq_disabled = 1; + } + else { + ts->disabled = 0; + ts->irq_disabled = 0; + } + + spin_unlock_irq(&ts->lock); + + return count; +} + +static DEVICE_ATTR(disable, 0664, ctw6120_disable_show, ctw6120_disable_store); + +static struct attribute *ctw6120_attributes[] = { + &dev_attr_pen_down.attr, + &dev_attr_disable.attr, + NULL, +}; + +static struct attribute_group ctw6120_attr_group = { + .attrs = ctw6120_attributes, +}; + +static int ctw6120_read(struct i2c_client *client, char reg, unsigned char *buf, int size) +{ + int ret; + /* send request to controller */ + ret = i2c_master_send(client, ®, 1); + if (ret < 0) + return ret; + + /* read data from controller */ + ret = i2c_master_recv(client, buf, size); + if (ret < 0) + return ret; + if (ret != size) + return -EIO; + return 0; +} + + +static int ctw6120_collect_report(struct ctw6120 *ts) +{ + int ret; + unsigned char touch_regs[26]; + + + ret = -1; + + /* read all the data from controller */ + ctw6120_read(ts->client, 0xF9, touch_regs, 26); + + if (unlikely(!touch_regs[3])) { + + /* check for transition state */ + if (ts->pendown) { + //input_mt_sync(ts->input); + input_report_key(ts->input, BTN_TOUCH, 0); + input_report_abs(ts->input, ABS_PRESSURE, 0); + input_sync(ts->input); + ts->pendown = 0; + } + + + } else { + unsigned short curr_x; + unsigned short curr_y; + unsigned short curr_x2; + unsigned short curr_y2; + + curr_x = (touch_regs[5] << 8) + touch_regs[6]; + curr_x = curr_x & 0x7FF; + + curr_y = (touch_regs[7] << 8) + touch_regs[8]; + curr_y &= 0xFFF; + + curr_x2 = (touch_regs[9] << 8) + touch_regs[10]; + curr_x2 = curr_x2 & 0x7FF; + + curr_y2 = (touch_regs[11] << 8) + touch_regs[12]; + curr_y2 &= 0xFFF; + + /* report pendown event if need */ + if (!ts->pendown) { + + input_report_key(ts->input, BTN_TOUCH, 1); + ts->pendown = 1; + } + + curr_x = (curr_x * 800) / 1790; + curr_y = (curr_y * 480) / 1024; + + curr_x2 = (curr_x2 * 800) / 1790; + curr_y2 = (curr_y2 * 480) / 1024; + + + + /* set data to be reported */ + input_report_abs(ts->input, ABS_X, curr_x); + input_report_abs(ts->input, ABS_Y, curr_y); + input_report_abs(ts->input, ABS_PRESSURE, 100); /* FIXME: calculate real pressure */ +//printk("%s:%d: x = %u y = %u\n", __func__, __LINE__, curr_x, curr_y); +#if 0 + if (touch_regs[3] > 1){ + input_report_abs(ts->input, ABS_MT_POSITION_X, curr_x2); + input_report_abs(ts->input, ABS_MT_POSITION_Y, curr_y2); +//printk("%s:%d: x2 = %u y2 = %u\n", __func__, __LINE__, curr_x, curr_y); + input_mt_sync(ts->input); + } +#endif + /* report to input subsystem */ + input_sync(ts->input); + // printk(KERN_INFO "x %d, y %d, x2 %d, y2 %d num %d\n", curr_x, curr_y, curr_x2, curr_y2, touch_regs[3]); + ret = 0; + + } + + return ret; +} + +static void ctw6120_work(struct work_struct *work) +{ + int ret; + struct ctw6120 *ts = container_of(work, struct ctw6120, work); + + /* collect data from controller and report it to input subsytem */ + ret = ctw6120_collect_report(ts); + + if (!ret) + /* arm timer for collection of next sample */ + hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_MODE_REL); +} + +static enum hrtimer_restart ctw6120_timer(struct hrtimer *handle) +{ + struct ctw6120 *ts = container_of(handle, struct ctw6120, timer); + ts->irq_disabled = 1; +// printk(KERN_ERR "t\n"); + + spin_lock(&ts->lock); + /* schedule the work */ + if (!work_pending(&ts->work)) + schedule_work(&ts->work); + + spin_unlock(&ts->lock); + + return HRTIMER_NORESTART; +} + +static irqreturn_t ctw6120_irq(int irq, void *handle) +{ + struct ctw6120 *ts = handle; + + /* schedule the work */ + if (!work_pending(&ts->work)) + schedule_work(&ts->work); + + return IRQ_HANDLED; +} + +static int __devinit ctw6120_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct ctw6120 *ts; + struct input_dev *input_dev; + unsigned char revid; + int status; + char reg = 0; + int ret; + + /* check i2c interface */ + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { + dev_dbg(&client->dev, "can't talk I2C\n"); + return -EIO; + } + + reg = 0; + i2c_master_send(client, ®, 1); + + /* read data from controller */ + ret = i2c_master_recv(client, &revid, sizeof(revid)); + if (ret != sizeof(revid)) + return -EIO; + dev_info(&client->dev, "Rev.%x touchscreen, irq %d\n", revid, client->irq); + printk(KERN_ERR "CTW6120: revid %x\n",revid ); + + // Set static pointer to reg zero + reg=CTW6120_STATUS_REG; + i2c_master_send(client, ®, 1); + + /* allocate touchscreen data structure */ + ts = kzalloc(sizeof(struct ctw6120), GFP_KERNEL); + /* store touchscreen data structure in the i2c driver context */ + i2c_set_clientdata(client, ts); + + /* store I2C interface for comunication with controller */ + ts->client = client; + + /* initializa the timer */ + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ts->timer.function = ctw6120_timer; + + /* initialize spin lock */ + spin_lock_init(&ts->lock); + + /* install interrupt handler */ + if (request_irq(client->irq, ctw6120_irq, IRQF_TRIGGER_FALLING, + client->dev.driver->name, ts)) { + printk(KERN_ERR "CTW6120: unable install IRQ\n"); + } + /* enable IRQ handling */ + ts->irq_disabled = 0; + + /* register input device */ + input_dev = input_allocate_device(); + /* set driver name */ + input_dev->name = "CTW6120 Touchscreen"; + /* store phys structure */ + snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); + input_dev->phys = ts->phys; + /* store I2C interface for in the input descriptor */ + input_dev->dev.parent = &client->dev; + + + + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + + + /* set range of the parameters */ + input_set_abs_params(input_dev, ABS_X, 0, 799, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, 479, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); + + + status = sysfs_create_group(&client->dev.kobj, &ctw6120_attr_group); + if (status) + printk(KERN_ERR "CTW6120: can't create fs group"); + + /* register input device */ + status = input_register_device(input_dev); + + /* store input device descriptor for further use */ + ts->input = input_dev; + /* set pen status as penup */ + ts->pendown = 0; + + /* initialize work queue */ + INIT_WORK(&ts->work, ctw6120_work); + + return status; +} + +static int __devexit ctw6120_remove(struct i2c_client *client) +{ + return 0; +} + +static const struct i2c_device_id ctw6120_id[] = { + { "ctw6120", 0 }, + { } +}; + +static struct i2c_driver ctw6120_driver = { + .driver = { + .name = "ctw6120", + .owner = THIS_MODULE, + }, + .probe = ctw6120_probe, + .remove = __devexit_p(ctw6120_remove), + .id_table = ctw6120_id, +}; + +static int __init ctw6120_init(void) +{ + return i2c_add_driver(&ctw6120_driver); +} +module_init(ctw6120_init); + +static void __exit ctw6120_exit(void) +{ + i2c_del_driver(&ctw6120_driver); +} +module_exit(ctw6120_exit); + +MODULE_DESCRIPTION("CTW6120 TouchScreen Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("i2c:ctw6120"); +MODULE_AUTHOR("Alex Bikhdriker"); diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c new file mode 100644 index 0000000..bde9adf --- /dev/null +++ b/drivers/input/touchscreen/tsc2004.c @@ -0,0 +1,544 @@ +/* + * drivers/input/touchscreen/tsc2004.c + * + * Copyright (C) 2009 Texas Instruments Inc + * Author: Vaibhav Hiremath <hvaibhav@ti.com> + * + * Using code from: + * - tsc2007.c + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/i2c.h> +#include <linux/i2c/tsc2004.h> + +/* Variscite touch panel manual collaboration values */ +#define VARISCITE_TS_X_MIN 120 +#define VARISCITE_TS_X_MAX 3960 +#define VARISCITE_TS_Y_MIN 280 +#define VARISCITE_TS_Y_MAX 3850 + +#define TS_POLL_DELAY 1 /* ms delay between samples */ +#define TS_POLL_PERIOD 30 /* ms delay between samples */ + +/* Control byte 0 */ +#define TSC2004_CMD0(addr, pnd, rw) ((addr<<3)|(pnd<<1)|rw) +/* Control byte 1 */ +#define TSC2004_CMD1(cmd, mode, rst) ((1<<7)|(cmd<<4)|(mode<<2)|(rst<<1)) + +/* Command Bits */ +#define READ_REG 1 +#define WRITE_REG 0 +#define SWRST_TRUE 1 +#define SWRST_FALSE 0 +#define PND0_TRUE 1 +#define PND0_FALSE 0 + +/* Converter function mapping */ +enum convertor_function { + MEAS_X_Y_Z1_Z2, /* Measure X,Y,z1 and Z2: 0x0 */ + MEAS_X_Y, /* Measure X and Y only: 0x1 */ + MEAS_X, /* Measure X only: 0x2 */ + MEAS_Y, /* Measure Y only: 0x3 */ + MEAS_Z1_Z2, /* Measure Z1 and Z2 only: 0x4 */ + MEAS_AUX, /* Measure Auxillary input: 0x5 */ + MEAS_TEMP1, /* Measure Temparature1: 0x6 */ + MEAS_TEMP2, /* Measure Temparature2: 0x7 */ + MEAS_AUX_CONT, /* Continuously measure Auxillary input: 0x8 */ + X_DRV_TEST, /* X-Axis drivers tested 0x9 */ + Y_DRV_TEST, /* Y-Axis drivers tested 0xA */ + /*Command Reserved*/ + SHORT_CKT_TST = 0xC, /* Short circuit test: 0xC */ + XP_XN_DRV_STAT, /* X+,Y- drivers status: 0xD */ + YP_YN_DRV_STAT, /* X+,Y- drivers status: 0xE */ + YP_XN_DRV_STAT /* Y+,X- drivers status: 0xF */ +}; + +/* Register address mapping */ +enum register_address { + X_REG, /* X register: 0x0 */ + Y_REG, /* Y register: 0x1 */ + Z1_REG, /* Z1 register: 0x2 */ + Z2_REG, /* Z2 register: 0x3 */ + AUX_REG, /* AUX register: 0x4 */ + TEMP1_REG, /* Temp1 register: 0x5 */ + TEMP2_REG, /* Temp2 register: 0x6 */ + STAT_REG, /* Status Register: 0x7 */ + AUX_HGH_TH_REG, /* AUX high threshold register: 0x8 */ + AUX_LOW_TH_REG, /* AUX low threshold register: 0x9 */ + TMP_HGH_TH_REG, /* Temp high threshold register:0xA */ + TMP_LOW_TH_REG, /* Temp low threshold register: 0xB */ + CFR0_REG, /* Configuration register 0: 0xC */ + CFR1_REG, /* Configuration register 1: 0xD */ + CFR2_REG, /* Configuration register 2: 0xE */ + CONV_FN_SEL_STAT /* Convertor function select register: 0xF */ +}; + +/* Supported Resolution modes */ +enum resolution_mode { + MODE_10BIT, /* 10 bit resolution */ + MODE_12BIT /* 12 bit resolution */ +}; + +/* Configuraton register bit fields */ +/* CFR0 */ +#define PEN_STS_CTRL_MODE (1<<15) +#define ADC_STS (1<<14) +#define RES_CTRL (1<<13) +#define ADC_CLK_4MHZ (0<<11) +#define ADC_CLK_2MHZ (1<<11) +#define ADC_CLK_1MHZ (2<<11) +#define PANEL_VLTG_STB_TIME_0US (0<<8) +#define PANEL_VLTG_STB_TIME_100US (1<<8) +#define PANEL_VLTG_STB_TIME_500US (2<<8) +#define PANEL_VLTG_STB_TIME_1MS (3<<8) +#define PANEL_VLTG_STB_TIME_5MS (4<<8) +#define PANEL_VLTG_STB_TIME_10MS (5<<8) +#define PANEL_VLTG_STB_TIME_50MS (6<<8) +#define PANEL_VLTG_STB_TIME_100MS (7<<8) + +/* CFR2 */ +#define PINTS1 (1<<15) +#define PINTS0 (1<<14) +#define MEDIAN_VAL_FLTR_SIZE_1 (0<<12) +#define MEDIAN_VAL_FLTR_SIZE_3 (1<<12) +#define MEDIAN_VAL_FLTR_SIZE_7 (2<<12) +#define MEDIAN_VAL_FLTR_SIZE_15 (3<<12) +#define AVRG_VAL_FLTR_SIZE_1 (0<<10) +#define AVRG_VAL_FLTR_SIZE_3_4 (1<<10) +#define AVRG_VAL_FLTR_SIZE_7_8 (2<<10) +#define AVRG_VAL_FLTR_SIZE_16 (3<<10) +#define MAV_FLTR_EN_X (1<<4) +#define MAV_FLTR_EN_Y (1<<3) +#define MAV_FLTR_EN_Z (1<<2) + +#define MAX_12BIT ((1 << 12) - 1) +#define MEAS_MASK 0xFFF + +struct ts_event { + u16 x; + u16 y; + u16 z1, z2; +}; + +struct tsc2004 { + struct input_dev *input; + char phys[32]; + struct delayed_work work; + + struct i2c_client *client; + + u16 model; + u16 x_plate_ohms; + + bool pendown; + int irq; + + int (*get_pendown_state)(void); + void (*clear_penirq)(void); +}; + +static inline int tsc2004_read_word_data(struct tsc2004 *tsc, u8 cmd) +{ + s32 data; + u16 val; + + data = i2c_smbus_read_word_data(tsc->client, cmd); + if (data < 0) { + dev_err(&tsc->client->dev, "i2c io (read) error: %d\n", data); + return data; + } + + /* The protocol and raw data format from i2c interface: + * S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P + * Where DataLow has [D11-D4], DataHigh has [D3-D0 << 4 | Dummy 4bit]. + */ + val = swab16(data); + + dev_dbg(&tsc->client->dev, "data: 0x%x, val: 0x%x\n", data, val); + + return val; +} + +static inline int tsc2004_write_word_data(struct tsc2004 *tsc, u8 cmd, u16 data) +{ + u16 val; + + val = swab16(data); + return i2c_smbus_write_word_data(tsc->client, cmd, val); +} + +static inline int tsc2004_write_cmd(struct tsc2004 *tsc, u8 value) +{ + return i2c_smbus_write_byte(tsc->client, value); +} + +static int tsc2004_prepare_for_reading(struct tsc2004 *ts) +{ + int err; + int cmd, data; + + /* Reset the TSC, configure for 12 bit */ + cmd = TSC2004_CMD1(MEAS_X_Y_Z1_Z2, MODE_12BIT, SWRST_TRUE); + err = tsc2004_write_cmd(ts, cmd); + if (err < 0) + return err; + + + /* Enable interrupt for PENIRQ and DAV */ + cmd = TSC2004_CMD0(CFR2_REG, PND0_FALSE, WRITE_REG); + data = PINTS1 | PINTS0 | MEDIAN_VAL_FLTR_SIZE_15 | + AVRG_VAL_FLTR_SIZE_7_8 | MAV_FLTR_EN_X | MAV_FLTR_EN_Y | + MAV_FLTR_EN_Z; + err = tsc2004_write_word_data(ts, cmd, data); + if (err < 0) + return err; + + /* Configure the TSC in TSMode 1 */ + cmd = TSC2004_CMD0(CFR0_REG, PND0_FALSE, WRITE_REG); + data = PEN_STS_CTRL_MODE | ADC_CLK_2MHZ | PANEL_VLTG_STB_TIME_1MS; + err = tsc2004_write_word_data(ts, cmd, data); + if (err < 0) + return err; + + /* Enable x, y, z1 and z2 conversion functions */ + cmd = TSC2004_CMD1(MEAS_X_Y_Z1_Z2, MODE_12BIT, SWRST_FALSE); + err = tsc2004_write_cmd(ts, cmd); + if (err < 0) + return err; + + return 0; +} + +static void tsc2004_read_values(struct tsc2004 *tsc, struct ts_event *tc) +{ + int cmd; + + /* Read X Measurement */ + cmd = TSC2004_CMD0(X_REG, PND0_FALSE, READ_REG); + tc->x = tsc2004_read_word_data(tsc, cmd); + + /* Read Y Measurement */ + cmd = TSC2004_CMD0(Y_REG, PND0_FALSE, READ_REG); + tc->y = tsc2004_read_word_data(tsc, cmd); + + /* Read Z1 Measurement */ + cmd = TSC2004_CMD0(Z1_REG, PND0_FALSE, READ_REG); + tc->z1 = tsc2004_read_word_data(tsc, cmd); + + /* Read Z2 Measurement */ + cmd = TSC2004_CMD0(Z2_REG, PND0_FALSE, READ_REG); + tc->z2 = tsc2004_read_word_data(tsc, cmd); + + + tc->x &= MEAS_MASK; + tc->y &= MEAS_MASK; + tc->z1 &= MEAS_MASK; + tc->z2 &= MEAS_MASK; + + /* Prepare for touch readings */ + if (tsc2004_prepare_for_reading(tsc) < 0) + dev_dbg(&tsc->client->dev, "Failed to prepare TSC for next" + "reading\n"); +} + +static u32 tsc2004_calculate_pressure(struct tsc2004 *tsc, struct ts_event *tc) +{ + u32 rt = 0; + + /* range filtering */ + if (tc->x == MAX_12BIT) + tc->x = 0; + + if (likely(tc->x && tc->z1)) { + /* compute touch pressure resistance using equation #1 */ + rt = tc->z2 - tc->z1; + rt *= tc->x; + rt *= tsc->x_plate_ohms; + rt /= tc->z1; + rt = (rt + 2047) >> 12; + } + + return rt; +} + +static void tsc2004_send_up_event(struct tsc2004 *tsc) +{ + struct input_dev *input = tsc->input; + + dev_dbg(&tsc->client->dev, "UP\n"); + + input_report_key(input, BTN_TOUCH, 0); + input_report_abs(input, ABS_PRESSURE, 0); + input_sync(input); +} + +static void tsc2004_work(struct work_struct *work) +{ + struct tsc2004 *ts = + container_of(to_delayed_work(work), struct tsc2004, work); + struct ts_event tc; + u32 rt; + + /* + * NOTE: We can't rely on the pressure to determine the pen down + * state, even though this controller has a pressure sensor. + * The pressure value can fluctuate for quite a while after + * lifting the pen and in some cases may not even settle at the + * expected value. + * + * The only safe way to check for the pen up condition is in the + * work function by reading the pen signal state (it's a GPIO + * and IRQ). Unfortunately such callback is not always available, + * in that case we have rely on the pressure anyway. + */ + if (ts->get_pendown_state) { + if (unlikely(!ts->get_pendown_state())) { + tsc2004_send_up_event(ts); + ts->pendown = false; + goto out; + } + + dev_dbg(&ts->client->dev, "pen is still down\n"); + } + + tsc2004_read_values(ts, &tc); + + rt = tsc2004_calculate_pressure(ts, &tc); + if (rt > MAX_12BIT) { + /* + * Sample found inconsistent by debouncing or pressure is + * beyond the maximum. Don't report it to user space, + * repeat at least once more the measurement. + */ + dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); + goto out; + + } + + if (rt) { + struct input_dev *input = ts->input; + + if (!ts->pendown) { + dev_dbg(&ts->client->dev, "DOWN\n"); + + input_report_key(input, BTN_TOUCH, 1); + ts->pendown = true; + } + + if (tc.x < VARISCITE_TS_X_MIN) + tc.x = VARISCITE_TS_X_MIN; + if (tc.x > VARISCITE_TS_X_MAX) + tc.x = VARISCITE_TS_X_MAX; + if (tc.y < VARISCITE_TS_Y_MIN) + tc.y = VARISCITE_TS_Y_MIN; + if (tc.y > VARISCITE_TS_Y_MAX) + tc.y = VARISCITE_TS_Y_MAX; + + input_report_abs(input, ABS_X, tc.x); + input_report_abs(input, ABS_Y, tc.y); + input_report_abs(input, ABS_PRESSURE, rt); + + input_sync(input); + + dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", + tc.x, tc.y, rt); + + } else if (!ts->get_pendown_state && ts->pendown) { + /* + * We don't have callback to check pendown state, so we + * have to assume that since pressure reported is 0 the + * pen was lifted up. + */ + tsc2004_send_up_event(ts); + ts->pendown = false; + } + + out: + if (ts->pendown) + schedule_delayed_work(&ts->work, + msecs_to_jiffies(TS_POLL_PERIOD)); + else + enable_irq(ts->irq); +} + +static irqreturn_t tsc2004_irq(int irq, void *handle) +{ + struct tsc2004 *ts = handle; + + if (!ts->get_pendown_state || likely(ts->get_pendown_state())) { + disable_irq_nosync(ts->irq); + schedule_delayed_work(&ts->work, + msecs_to_jiffies(TS_POLL_DELAY)); + } + + if (ts->clear_penirq) + ts->clear_penirq(); + + return IRQ_HANDLED; +} + +static void tsc2004_free_irq(struct tsc2004 *ts) +{ + free_irq(ts->irq, ts); + if (cancel_delayed_work_sync(&ts->work)) { + /* + * Work was pending, therefore we need to enable + * IRQ here to balance the disable_irq() done in the + * interrupt handler. + */ + enable_irq(ts->irq); + } +} + +static int __devinit tsc2004_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tsc2004 *ts; + struct tsc2004_platform_data *pdata = pdata = client->dev.platform_data; + struct input_dev *input_dev; + int err; + + printk(" tsc2004_probe \n"); + + if (!pdata) { + dev_err(&client->dev, "platform data is required!\n"); + return -EINVAL; + } + printk("b i2c_check_functionality \n"); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) + return -EIO; + + dev_dbg(&ts->client->dev, "tsc2004_probe check functionality\n"); + + ts = kzalloc(sizeof(struct tsc2004), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ts || !input_dev) { + err = -ENOMEM; + goto err_free_mem; + } + + ts->client = client; + ts->irq = client->irq; + ts->input = input_dev; + INIT_DELAYED_WORK(&ts->work, tsc2004_work); + + ts->model = pdata->model; + ts->x_plate_ohms = pdata->x_plate_ohms; + ts->get_pendown_state = pdata->get_pendown_state; + ts->clear_penirq = pdata->clear_penirq; + + snprintf(ts->phys, sizeof(ts->phys), + "%s/input0", dev_name(&client->dev)); + + input_dev->name = "TSC2004 Touchscreen"; + input_dev->phys = ts->phys; + input_dev->id.bustype = BUS_I2C; + + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + + input_set_abs_params(input_dev, ABS_X, VARISCITE_TS_X_MIN, VARISCITE_TS_X_MAX, 0, 0); + input_set_abs_params(input_dev, ABS_Y, VARISCITE_TS_Y_MIN, VARISCITE_TS_Y_MAX, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); + + if (pdata->init_platform_hw) + pdata->init_platform_hw(); + + err = request_irq(ts->irq, tsc2004_irq, IRQF_TRIGGER_FALLING, + client->dev.driver->name, ts); + if (err < 0) { + dev_err(&client->dev, "irq %d busy?\n", ts->irq); + goto err_free_mem; + } + + /* Prepare for touch readings */ + err = tsc2004_prepare_for_reading(ts); + if (err < 0) + goto err_free_irq; + err = input_register_device(input_dev); + if (err) + goto err_free_irq; + + i2c_set_clientdata(client, ts); + + return 0; + + err_free_irq: + tsc2004_free_irq(ts); + if (pdata->exit_platform_hw) + pdata->exit_platform_hw(); + err_free_mem: + input_free_device(input_dev); + kfree(ts); + return err; +} + +static int __devexit tsc2004_remove(struct i2c_client *client) +{ + struct tsc2004 *ts = i2c_get_clientdata(client); + struct tsc2004_platform_data *pdata = client->dev.platform_data; + + tsc2004_free_irq(ts); + + if (pdata->exit_platform_hw) + pdata->exit_platform_hw(); + + input_unregister_device(ts->input); + kfree(ts); + + return 0; +} + +static struct i2c_device_id tsc2004_idtable[] = { + { "tsc2004", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, tsc2004_idtable); + +static struct i2c_driver tsc2004_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "tsc2004" + }, + .id_table = tsc2004_idtable, + .probe = tsc2004_probe, + .remove = __devexit_p(tsc2004_remove), +}; + +static int __init tsc2004_init(void) +{ + return i2c_add_driver(&tsc2004_driver); +} + +static void __exit tsc2004_exit(void) +{ + i2c_del_driver(&tsc2004_driver); +} + +module_init(tsc2004_init); +module_exit(tsc2004_exit); + +MODULE_AUTHOR("Vaibhav Hiremath <hvaibhav@ti.com>"); +MODULE_DESCRIPTION("TSC2004 TouchScreen Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 5e313e9..636f42f 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -28,6 +28,8 @@ #include "ks8851.h" +static u8 boot_mac_addr[ETH_ALEN] = {0}; + /** * struct ks8851_rxctrl - KS8851 driver rx control * @mchash: Multicast hash-table data. @@ -429,19 +431,34 @@ static void ks8851_init_mac(struct ks8851_net *ks) { struct net_device *dev = ks->netdev; - /* first, try reading what we've got already */ - if (ks->rc_ccr & CCR_EEPROM) { - ks8851_read_mac_addr(dev); - if (is_valid_ether_addr(dev->dev_addr)) - return; + if (is_valid_ether_addr(boot_mac_addr)) { + memcpy(dev->dev_addr, boot_mac_addr, sizeof(boot_mac_addr)); + netif_dbg(ks, rx_status, ks->netdev, "MAC address set from bootargs"); + } + else { + eth_hw_addr_random(dev); + netif_dbg(ks, rx_status, ks->netdev, "MAC address set to random_ether_addr"); + } + ks8851_write_mac_addr(dev); +} + +static int __init ks8851_boot_setup(char* str) +{ + int i; - netdev_err(ks->netdev, "invalid mac address read %pM\n", - dev->dev_addr); + /* Parse the colon separated Ethernet station address */ + for (i = 0; i < ETH_ALEN; i++) { + unsigned int tmp; + if (sscanf(str + 3*i, "%2x", &tmp) != 1) { + printk("ks8851_boot_setup: malformed station address\n"); + return 0; + } + boot_mac_addr[i] = (u8)tmp; } - eth_hw_addr_random(dev); - ks8851_write_mac_addr(dev); + return 1; } +__setup("eth.ks8851=", ks8851_boot_setup); /** * ks8851_irq - device interrupt handler diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 00103a8..72abe58 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -29,6 +29,7 @@ #include <linux/crc32.h> #include <linux/usb/usbnet.h> #include <linux/slab.h> +#include <linux/ctype.h> #include "smsc75xx.h" #define SMSC_CHIPNAME "smsc75xx" @@ -76,6 +77,7 @@ struct usb_context { struct usbnet *dev; }; +static u8 boot_mac_addr[ETH_ALEN] = {0}; static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); @@ -604,21 +606,33 @@ static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) static void smsc75xx_init_mac_address(struct usbnet *dev) { - /* try reading mac address from EEPROM */ - if (smsc75xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, - dev->net->dev_addr) == 0) { - if (is_valid_ether_addr(dev->net->dev_addr)) { - /* eeprom values are valid so use them */ - netif_dbg(dev, ifup, dev->net, - "MAC address read from EEPROM"); - return; + if (is_valid_ether_addr(boot_mac_addr)) { + memcpy(dev->net->dev_addr, boot_mac_addr, sizeof(boot_mac_addr)); + netif_dbg(dev, ifup, dev->net, "MAC address set from bootargs"); + } + else { + eth_hw_addr_random(dev->net); + netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr"); + } +} + +static int __init smsc7500_boot_setup(char* str) +{ + int i; + + /* Parse the colon separated Ethernet station address */ + for (i = 0; i < ETH_ALEN; i++) { + unsigned int tmp; + if (sscanf(str + 3*i, "%2x", &tmp) != 1) { + printk("smsc7500_boot_setup: malformed station address\n"); + return 0; } + boot_mac_addr[i] = (u8)tmp; } - /* no eeprom, or eeprom values are invalid. generate random MAC */ - eth_hw_addr_random(dev->net); - netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr"); + return 1; } +__setup("eth.smsc=", smsc7500_boot_setup); static int smsc75xx_set_mac_address(struct usbnet *dev) { @@ -642,6 +656,18 @@ static int smsc75xx_set_mac_address(struct usbnet *dev) return 0; } +static bool enable_gigabit = false; + +static int __init smsc75xx_phy_gb_enable_setup(char* str) +{ + if (strcmp(str, "true") == 0) { + enable_gigabit = true; + } + + return 1; +} +__setup("phy.smsc.gb_enable=", smsc75xx_phy_gb_enable_setup); + static int smsc75xx_phy_initialize(struct usbnet *dev) { int bmcr, ret, timeout = 0; @@ -673,8 +699,10 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + + /* Gbit ethernet extends SOM power consumption and heat by 0.5Watt => force 10/100 by default */ smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000, - ADVERTISE_1000FULL); + enable_gigabit?ADVERTISE_1000FULL:0 ); /* read and write to clear phy interrupt status */ ret = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC); diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c index e7cc4de..d3c6cff 100644 --- a/drivers/usb/gadget/f_uac2.c +++ b/drivers/usb/gadget/f_uac2.c @@ -463,7 +463,7 @@ snd_fail: return err; } -static int __devexit snd_uac2_remove(struct platform_device *pdev) +static int snd_uac2_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index e42f9dc..9eadd9b 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c @@ -486,6 +486,56 @@ static struct panel_config generic_dpi_panels[] = { OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC, .name = "primeview_pd104slf", }, + /*URT_UMSH_8423MD_T */ + { + { + .x_res = 800, + .y_res = 480, + + .pixel_clock = 27927, + + .hsw = 28, + .hfp = 29, + .hbp = 17, + + .vsw = 3, + .vfp = 13, + .vbp = 20, + }, + .acbi = 0x0, + .acb = 0x0, + .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS , + .power_on_delay = 0, + .power_off_delay = 0, + .name = "URT_UMSH_8423MD_T", + }, + + /*ETM_070001ADH6*/ + { + { + .x_res = 800, + .y_res = 480, + + .pixel_clock = 30000, + + .hsw = 28, + .hfp = 129, + .hbp = 17, + + + .vsw = 3, + .vfp = 32, + .vbp = 20, + }, + .acbi = 0x0, + .acb = 0x0, + .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS , + .power_on_delay = 0, + .power_off_delay = 0, + .name = "ETM_070001ADH6", + }, }; struct panel_drv_data { diff --git a/include/linux/i2c/ctw6120.h b/include/linux/i2c/ctw6120.h new file mode 100644 index 0000000..fb84d4f --- /dev/null +++ b/include/linux/i2c/ctw6120.h @@ -0,0 +1,74 @@ +/* + * ctw6120.h - header for TWL4030 PM and audio CODEC device + * + * Copyright (C) 2010 Variscite LTD. + * + * 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-1307 USA + * + */ + +#ifndef __CTW6120_H_ +#define __CTW6120_H_ + +#include <linux/types.h> + + +#define CTW6120_STATUS_REG 0x00 +#define CTW6120_X_HIGH_REG 0x01 +#define CTW6120_X_LOW_REG 0x02 +#define CTW6120_Y_HIGH_REG 0x03 +#define CTW6120_Y_LOW_REG 0x04 +#define CTW6120_BUTTON_REG 0x05 +#define CTW6120_MOVEMENT_REG 0x06 +#define CTW6120_GESTURE_REG 0x09 +#define CTW6120_SLEEP_MODE_REG 0x0A +#define CTW6120_SENSITIVITY_REG 0x0B +#define CTW6120_FIRMWARE_REG 0x0C + + +#define CTW6120_STATUS_NO_FINGERS 0 +#define CTW6120_STATUS_1_FINGER 1 +#define CTW6120_STATUS_2_FINGERS 2 + +#define CTW6120_BUTTON_LEFT 1 +#define CTW6120_BUTTON_RIGHT 2 +#define CTW6120_BUTTON_MID 4 + +#define CTW6120_ZOOM_IN 1 +#define CTW6120_ZOOM_OUT -1 + +#define CTW6120_GESTURE_NONE 0x00 +#define CTW6120_GESTURE_ZOOM_IN 0x01 +#define CTW6120_GESTURE_ZOOM_OUT 0x02 +#define CTW6120_GESTURE_ST_PAN_UP 0x03 +#define CTW6120_GESTURE_ST_ROTATE_CW 0x04 +#define CTW6120_GESTURE_ST_PAN_RIGHT 0x05 +#define CTW6120_GESTURE_ST_PAN_DOWN 0x06 +#define CTW6120_GESTURE_ST_PAN_LEFT 0x07 +#define CTW6120_GESTURE_ST_ROTATE_CCW 0x08 +#define CTW6120_GESTURE_ST_CLICK 0x09 +#define CTW6120_GESTURE_MT_PAN_UP 0x0A +#define CTW6120_GESTURE_MT_PAN_RIGHT 0x0B +#define CTW6120_GESTURE_MT_PAN_DOWN 0x0C +#define CTW6120_GESTURE_MT_PAN_LEFT 0x0D +#define CTW6120_GESTURE_ST_DOUBLE_CLICK 0x0E +#define CTW6120_GESTURE_MT_CLICK 0x0F + +#define CTW6120_GESTURE_ZOOM ((CTW6120_GESTURE_ZOOM_IN) | (CTW6120_GESTURE_ZOOM_OUT)) + +#define CTW6120_SLEEP_ENTER 0x01 +#define CTW6120_SLEEP_ESCAPE 0x00 + +#endif /* __CTW6120_H_ */ \ No newline at end of file diff --git a/include/linux/i2c/tsc2004.h b/include/linux/i2c/tsc2004.h new file mode 100644 index 0000000..044c36f --- /dev/null +++ b/include/linux/i2c/tsc2004.h @@ -0,0 +1,17 @@ +#ifndef __LINUX_I2C_TSC2004_H +#define __LINUX_I2C_TSC2004_H + +/* linux/i2c/tsc2004.h */ + +struct tsc2004_platform_data { + u16 model; /* 2004. */ + u16 x_plate_ohms; + + int (*get_pendown_state)(void); + void (*clear_penirq)(void); /* If needed, clear 2nd level + interrupt source */ + int (*init_platform_hw)(void); + void (*exit_platform_hw)(void); +}; + +#endif diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index f59076d..c9d6f57 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -369,10 +369,7 @@ static void twl6040_hs_jack_report(struct snd_soc_codec *codec, /* Sync status */ status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS); - if (status & TWL6040_PLUGCOMP) - snd_soc_jack_report(jack, report, report); - else - snd_soc_jack_report(jack, 0, report); + snd_soc_jack_report(jack, report, report); mutex_unlock(&priv->mutex); } diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index b54ed61..d97b3f6 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -1304,11 +1304,11 @@ static __devinit int omap_abe_probe(struct platform_device *pdev) int ret; card->dev = &pdev->dev; - +/* if (!machine_is_omap_4430sdp() && !machine_is_omap4_panda() && !machine_is_omap5_sevm()) return -ENODEV; - +*/ pr_info("OMAP4/5 SoC init\n"); if (!pdata) {