summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Rawling <mwr@google.com>2022-06-22 01:54:08 +0000
committerAndroid Partner Code Review <android-gerrit-partner@google.com>2022-06-22 01:54:08 +0000
commit4c349bf85fc5efd40bb589ca9805f01994db136a (patch)
treeb356c07ff755d0e2b6deb1c3d6f28a653a4bbc30
parent12f5ef939fd2b70d83500556f5dc0a5af6789aaa (diff)
parent62d40e70d411f35f2f0f830a8405034597d23101 (diff)
downloadnanohub-4c349bf85fc5efd40bb589ca9805f01994db136a.tar.gz
Merge "Support hardware reset with ISP boot mode" into android-msm-eos-5.4
-rw-r--r--main.c90
-rw-r--r--nanohub.h1
2 files changed, 77 insertions, 14 deletions
diff --git a/main.c b/main.c
index cd84d55..2f771e1 100644
--- a/main.c
+++ b/main.c
@@ -103,7 +103,7 @@ static ssize_t nanohub_read(struct file *, char *, size_t, loff_t *);
static ssize_t nanohub_write(struct file *, const char *, size_t, loff_t *);
static unsigned int nanohub_poll(struct file *, poll_table *);
static int nanohub_release(struct inode *, struct file *);
-static int nanohub_hw_reset(struct nanohub_data *data);
+static int nanohub_hw_reset(struct nanohub_data *data, int boot_mode);
// Kernel client support.
static struct nanohub_data *priv_nanohub_data;
@@ -116,6 +116,7 @@ static const struct gpio_config gconf[] = {
{ PLAT_GPIO_DEF(wakeup, GPIOF_OUT_INIT_HIGH) },
{ PLAT_GPIO_DEF(nreset, GPIOF_OUT_INIT_HIGH) },
{ PLAT_GPIO_DEF(boot0, GPIOF_OUT_INIT_HIGH) },
+ { PLAT_GPIO_DEF(boot2, GPIOF_OUT_INIT_HIGH) },
{ PLAT_GPIO_DEF_IRQ(irq1, GPIOF_DIR_IN, 0) },
{ PLAT_GPIO_DEF_IRQ(irq2, GPIOF_DIR_IN, GPIO_OPT_OPTIONAL) },
};
@@ -562,6 +563,14 @@ static ssize_t nanohub_pin_boot0_get(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%d\n", gpio_get_value(pdata->boot0_gpio));
}
+static ssize_t nanohub_pin_boot2_get(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nanohub_data *data = dev_get_drvdata(dev);
+ const struct nanohub_platform_data *pdata = data->pdata;
+ return scnprintf(buf, PAGE_SIZE, "%d\n", gpio_get_value(pdata->boot2_gpio));
+}
+
static ssize_t nanohub_pin_nreset_set(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -590,6 +599,20 @@ static ssize_t nanohub_pin_boot0_set(struct device *dev,
return count;
}
+static ssize_t nanohub_pin_boot2_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct nanohub_data *data = dev_get_drvdata(dev);
+ const struct nanohub_platform_data *pdata = data->pdata;
+ if (count >= 1 && buf[0] == '0') {
+ gpio_set_value(pdata->boot2_gpio, 0);
+ } else if (count >= 1 && buf[0] == '1') {
+ gpio_set_value(pdata->boot2_gpio, 1);
+ }
+ return count;
+}
+
static ssize_t nanohub_app_info(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -771,15 +794,23 @@ static inline int nanohub_wakeup_unlock(struct nanohub_data *data)
return mode;
}
-static void __nanohub_hw_reset(struct nanohub_data *data, int boot0)
+// boot_mode represents the ISP mode for the NXP MCU.
+static void __nanohub_hw_reset(struct nanohub_data *data, int boot_mode)
{
const struct nanohub_platform_data *pdata = data->pdata;
- gpio_set_value(pdata->boot0_gpio, 0);
- // Reset the MCU twice as a workaround for b/227924872
- gpio_set_value(pdata->nreset_gpio, 0);
- usleep_range(1000, 2000);
- gpio_set_value(pdata->nreset_gpio, 1);
- usleep_range(1000, 2000);
+ int isp0 = boot_mode & 0x1;
+ int isp1 = (boot_mode & 0x2) >> 1;
+ int isp2 = (boot_mode & 0x4) >> 2;
+
+ if (isp1 != 1) {
+ // ISP1 is not connected and is pulled high in ISP mode.
+ pr_err("nanohub_hw_reset: invalid boot mode (%d), ISP pin1 must be high\n",
+ boot_mode);
+ return;
+ }
+ pr_info("nanohub_hw_reset: boot_mode=%d\n", boot_mode);
+ gpio_set_value(pdata->boot0_gpio, isp0);
+ gpio_set_value(pdata->boot2_gpio, isp2);
gpio_set_value(pdata->nreset_gpio, 0);
usleep_range(1000, 2000);
gpio_set_value(pdata->nreset_gpio, 1);
@@ -787,13 +818,13 @@ static void __nanohub_hw_reset(struct nanohub_data *data, int boot0)
nanohub_clear_err_cnt(data);
}
-static int nanohub_hw_reset(struct nanohub_data *data)
+static int nanohub_hw_reset(struct nanohub_data *data, int boot_mode)
{
int ret;
ret = nanohub_wakeup_lock(data, LOCK_MODE_RESET);
if (!ret) {
- __nanohub_hw_reset(data, 0);
+ __nanohub_hw_reset(data, boot_mode);
nanohub_wakeup_unlock(data);
}
@@ -805,9 +836,25 @@ static ssize_t nanohub_try_hw_reset(struct device *dev,
const char *buf, size_t count)
{
struct nanohub_data *data = dev_get_drvdata(dev);
+ #define BOOT_MODE_ARG_SIZE 10
+ char boot_mode_buf[BOOT_MODE_ARG_SIZE + 1];
+ int boot_mode;
int ret;
- ret = nanohub_hw_reset(data);
+ // Read the boot mode argument. (ascii, possibly unterminated)
+ if (count == 0 || count > BOOT_MODE_ARG_SIZE) {
+ pr_err("nanohub_try_hw_reset: invalid input\n");
+ return -EINVAL;
+ }
+ memcpy(boot_mode_buf, buf, count);
+ boot_mode_buf[count] = 0;
+ if (kstrtoint(boot_mode_buf, 0, &boot_mode) != 0) {
+ pr_err("nanohub_try_hw_reset: invalid boot mode %s\n",
+ boot_mode_buf);
+ return -EINVAL;
+ }
+
+ ret = nanohub_hw_reset(data, boot_mode);
return ret < 0 ? ret : count;
}
@@ -1041,7 +1088,9 @@ static void nanohub_download_firmware(struct device *dev)
if (data->irq1)
disable_irq(data->irq1);
- __nanohub_hw_reset(data, -1);
+ // FW download uses SERIAL_ISP mode.
+ int serial_isp = 0b110;
+ __nanohub_hw_reset(data, serial_isp);
ret = nanohub_bl_download_firmware(data, fw_entry->data,
fw_entry->size);
@@ -1245,6 +1294,7 @@ static struct device_attribute attributes[] = {
__ATTR(hw_reset, 0220, NULL, nanohub_try_hw_reset),
__ATTR(nreset, 0660, nanohub_pin_nreset_get, nanohub_pin_nreset_set),
__ATTR(boot0, 0660, nanohub_pin_boot0_get, nanohub_pin_boot0_set),
+ __ATTR(boot2, 0660, nanohub_pin_boot2_get, nanohub_pin_boot2_set),
#ifdef CONFIG_NANOHUB_BL_ST
__ATTR(lock, 0220, NULL, nanohub_lock_bl),
__ATTR(unlock, 0220, NULL, nanohub_unlock_bl),
@@ -1754,8 +1804,19 @@ static struct nanohub_platform_data *nanohub_parse_dt(struct device *dev)
goto free_pdata;
}
- /* optional (stm32f bootloader) */
- pdata->boot0_gpio = of_get_named_gpio(dt, "sensorhub,boot0-gpio", 0);
+ ret = pdata->boot0_gpio =
+ of_get_named_gpio(dt, "sensorhub,boot0-gpio", 0);
+ if (ret < 0) {
+ pr_err("nanohub: missing sensorhub,boot0-gpio in device tree\n");
+ goto free_pdata;
+ }
+
+ ret = pdata->boot2_gpio =
+ of_get_named_gpio(dt, "sensorhub,boot2-gpio", 0);
+ if (ret < 0) {
+ pr_err("nanohub: missing sensorhub,boot2-gpio in device tree\n");
+ goto free_pdata;
+ }
/* optional (spi) */
pdata->spi_cs_gpio = of_get_named_gpio(dt, "sensorhub,spi-cs-gpio", 0);
@@ -1964,6 +2025,7 @@ static void nanohub_release_gpios_irqs(struct nanohub_data *data)
gpio_free(pdata->wakeup_gpio);
gpio_set_value(pdata->boot0_gpio, 1);
gpio_free(pdata->boot0_gpio);
+ gpio_free(pdata->boot2_gpio);
}
struct iio_dev *nanohub_probe(struct device *dev, struct iio_dev *iio_dev)
diff --git a/nanohub.h b/nanohub.h
index 8060c56..29021b2 100644
--- a/nanohub.h
+++ b/nanohub.h
@@ -10,6 +10,7 @@ struct nanohub_platform_data {
u32 wakeup_gpio;
u32 nreset_gpio;
u32 boot0_gpio;
+ u32 boot2_gpio;
u32 irq1_gpio;
u32 irq2_gpio;
u32 spi_cs_gpio;