From 71b8f029e7efbf9d68e437e6487fb25dd603e081 Mon Sep 17 00:00:00 2001 From: Amy Maloche Date: Thu, 17 Jan 2013 11:50:24 -0800 Subject: [PATCH] input: atmel_mxt_ts: Allow bootloader address to be set The driver maintains a default mapping between appmode address and bootloader address. Some appmode addresses may have different corresponding bootloader addresses than what is currently mapped. When this is the case, looking through an array will not work and bootloader address must be passed in through device tree or pdata. Appmode address is already present in i2c client structure. With this support, firmware upgrade for mxt336s and mxt1664s touch controllers is now present. Change-Id: I605b4ae615f30a05620847a5a9af826bc906f1c3 Signed-off-by: Amy Maloche --- .../input/touchscreen/atmel-mxt-ts.txt | 2 + drivers/input/touchscreen/atmel_mxt_ts.c | 83 +++++++++++-------- include/linux/i2c/atmel_mxt_ts.h | 5 +- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt index bcea3554b1b..dde1a16c7c1 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt @@ -22,6 +22,8 @@ Required properties: - atmel,fw-name : firmware name to used for flashing firmware Optional property: + - atmel,bl-addr : bootloader address, by default is looked up + in mxt_slave_addresses structure - atmel,config : configuration parameter for the controller - atmel,i2c-pull-up : specify to indicate pull up is needed - vcc_i2c-supply : Power source required to pull up i2c bus diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 2e807acd846..a867fc9481d 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3,7 +3,7 @@ * * Copyright (C) 2010 Samsung Electronics Co.Ltd * Author: Joonyoung Shim - * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. * * 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 @@ -356,6 +356,7 @@ struct mxt_data { struct regulator *vcc_ana; struct regulator *vcc_dig; struct regulator *vcc_i2c; + struct mxt_address_pair addr_pair; #if defined(CONFIG_HAS_EARLYSUSPEND) struct early_suspend early_suspend; #endif @@ -470,9 +471,27 @@ static void mxt_dump_message(struct device *dev, dev_dbg(dev, "checksum:\t0x%x\n", message->checksum); } -static int mxt_switch_to_bootloader_address(struct mxt_data *data) +static int mxt_lookup_bootloader_address(struct mxt_data *data) { int i; + + for (i = 0; mxt_slave_addresses[i].application != 0; i++) { + if (mxt_slave_addresses[i].application == + data->client->addr) { + data->addr_pair.bootloader = + mxt_slave_addresses[i].bootloader; + return 0; + } + } + + dev_err(&data->client->dev, "Address 0x%02x not found in address table", + data->client->addr); + return -EINVAL; + +}; + +static int mxt_switch_to_bootloader_address(struct mxt_data *data) +{ struct i2c_client *client = data->client; if (data->state == BOOTLOADER) { @@ -480,27 +499,16 @@ static int mxt_switch_to_bootloader_address(struct mxt_data *data) return -EINVAL; } - for (i = 0; mxt_slave_addresses[i].application != 0; i++) { - if (mxt_slave_addresses[i].application == client->addr) { - dev_info(&client->dev, "Changing to bootloader address: " - "%02x -> %02x", - client->addr, - mxt_slave_addresses[i].bootloader); + dev_info(&client->dev, "Changing to bootloader address: 0x%02x -> 0x%02x", + client->addr, data->addr_pair.bootloader); - client->addr = mxt_slave_addresses[i].bootloader; - data->state = BOOTLOADER; - return 0; - } - } - - dev_err(&client->dev, "Address 0x%02x not found in address table", - client->addr); - return -EINVAL; + client->addr = data->addr_pair.bootloader; + data->state = BOOTLOADER; + return 0; } static int mxt_switch_to_appmode_address(struct mxt_data *data) { - int i; struct i2c_client *client = data->client; if (data->state == APPMODE) { @@ -508,23 +516,13 @@ static int mxt_switch_to_appmode_address(struct mxt_data *data) return -EINVAL; } - for (i = 0; mxt_slave_addresses[i].application != 0; i++) { - if (mxt_slave_addresses[i].bootloader == client->addr) { - dev_info(&client->dev, - "Changing to application mode address: " - "0x%02x -> 0x%02x", - client->addr, - mxt_slave_addresses[i].application); + dev_info(&client->dev, "Changing to application mode address: " \ + "0x%02x -> 0x%02x", client->addr, + data->addr_pair.application); - client->addr = mxt_slave_addresses[i].application; - data->state = APPMODE; - return 0; - } - } - - dev_err(&client->dev, "Address 0x%02x not found in address table", - client->addr); - return -EINVAL; + client->addr = data->addr_pair.application; + data->state = APPMODE; + return 0; } static int mxt_get_bootloader_version(struct i2c_client *client, u8 val) @@ -1655,9 +1653,11 @@ static int mxt_load_fw(struct device *dev, const char *fn) switch (data->info.family_id) { case MXT224_ID: case MXT224E_ID: + case MXT336S_ID: max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE; break; case MXT1386_ID: + case MXT1664S_ID: max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE; break; default: @@ -2564,6 +2564,12 @@ static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata) return -ENOMEM; } + rc = of_property_read_u32(np, "atmel,bl-addr", &temp_val); + if (rc && (rc != -EINVAL)) + dev_err(dev, "Unable to read bootloader address\n"); + else if (rc != -EINVAL) + pdata->bl_addr = (u8) temp_val; + pdata->config_array = info; for_each_child_of_node(np, temp) { @@ -2602,7 +2608,7 @@ static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata) } else info->build = (u8) temp_val; - info->bootldr_id = of_property_read_u32(temp, + rc = of_property_read_u32(temp, "atmel,bootldr-id", &temp_val); if (rc) { dev_err(dev, "Unable to read bootldr-id\n"); @@ -2767,6 +2773,13 @@ static int __devinit mxt_probe(struct i2c_client *client, mxt_power_on_delay(data); + data->addr_pair.application = data->client->addr; + + if (pdata->bl_addr) + data->addr_pair.bootloader = pdata->bl_addr; + else + mxt_lookup_bootloader_address(data); + error = mxt_initialize(data); if (error) goto err_reset_gpio_req; diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h index fe239932589..b903dfbd91e 100644 --- a/include/linux/i2c/atmel_mxt_ts.h +++ b/include/linux/i2c/atmel_mxt_ts.h @@ -3,7 +3,7 @@ * * Copyright (C) 2010 Samsung Electronics Co.Ltd * Author: Joonyoung Shim - * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. * * 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 @@ -32,8 +32,10 @@ /* Bootoader IDs */ #define MXT_BOOTLOADER_ID_224 0x0A #define MXT_BOOTLOADER_ID_224E 0x06 +#define MXT_BOOTLOADER_ID_336S 0x1A #define MXT_BOOTLOADER_ID_1386 0x01 #define MXT_BOOTLOADER_ID_1386E 0x10 +#define MXT_BOOTLOADER_ID_1664S 0x14 /* Config data for a given maXTouch controller with a specific firmware */ struct mxt_config_info { @@ -75,6 +77,7 @@ struct mxt_platform_data { int *key_codes; bool need_calibration; bool no_force_update; + u8 bl_addr; u8(*read_chg) (void); int (*init_hw) (bool);