diff options
author | Mark Rawling <mwr@google.com> | 2022-06-22 01:54:08 +0000 |
---|---|---|
committer | Android Partner Code Review <android-gerrit-partner@google.com> | 2022-06-22 01:54:08 +0000 |
commit | 4c349bf85fc5efd40bb589ca9805f01994db136a (patch) | |
tree | b356c07ff755d0e2b6deb1c3d6f28a653a4bbc30 | |
parent | 12f5ef939fd2b70d83500556f5dc0a5af6789aaa (diff) | |
parent | 62d40e70d411f35f2f0f830a8405034597d23101 (diff) | |
download | nanohub-4c349bf85fc5efd40bb589ca9805f01994db136a.tar.gz |
Merge "Support hardware reset with ISP boot mode" into android-msm-eos-5.4
-rw-r--r-- | main.c | 90 | ||||
-rw-r--r-- | nanohub.h | 1 |
2 files changed, 77 insertions, 14 deletions
@@ -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) @@ -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; |