struct pinctrl *pinctrl;
struct pinctrl_state *pin_default;
+
+ /* V2: SPI Bus control */
+ int spi_en_gpio;
+ bool spi_en_polarity_high;
};
/*
/* Hold APB in reset state */
assert_reset(apb->resetn_gpio);
+ if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
+ gpio_is_valid(apb->spi_en_gpio))
+ devm_gpio_free(dev, apb->spi_en_gpio);
+
/* Enable power to APB */
if (!IS_ERR(apb->vcore)) {
ret = regulator_enable(apb->vcore);
return ret;
}
+ if (gpio_is_valid(apb->spi_en_gpio)) {
+ unsigned long flags;
+
+ if (apb->spi_en_polarity_high)
+ flags = GPIOF_OUT_INIT_HIGH;
+ else
+ flags = GPIOF_OUT_INIT_LOW;
+
+ ret = devm_gpio_request_one(dev, apb->spi_en_gpio,
+ flags, "apb_spi_en");
+ if (ret) {
+ dev_err(dev, "Failed requesting SPI bus en gpio %d\n",
+ apb->spi_en_gpio);
+ return ret;
+ }
+ }
+
/* for flashing device should be in reset state */
assert_reset(apb->resetn_gpio);
apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING;
static int standby_boot_seq(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
if (apb->init_disabled)
apb->state == ARCHE_PLATFORM_STATE_OFF)
return 0;
+ if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
+ gpio_is_valid(apb->spi_en_gpio))
+ devm_gpio_free(dev, apb->spi_en_gpio);
+
/*
* As per WDM spec, do nothing
*
static void poweroff_seq(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF)
return;
+ if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING &&
+ gpio_is_valid(apb->spi_en_gpio))
+ devm_gpio_free(dev, apb->spi_en_gpio);
+
/* disable the clock */
if (gpio_is_valid(apb->clk_en_gpio))
gpio_set_value(apb->clk_en_gpio, 0);
return PTR_ERR(apb->pin_default);
}
+ /* Only applicable for platform >= V2 */
+ apb->spi_en_gpio = of_get_named_gpio(np, "spi-en-gpio", 0);
+ if (apb->spi_en_gpio >= 0) {
+ if (of_property_read_bool(pdev->dev.of_node,
+ "spi-en-active-high"))
+ apb->spi_en_polarity_high = true;
+ }
+
return 0;
}
return 0;
}
-static int apb_fw_flashing_state(struct device *dev, void *data)
-{
- int ret;
-
- ret = apb_ctrl_fw_flashing(dev);
- if (ret)
- dev_warn(dev, "failed to switch to fw flashing state\n");
-
- /*Child nodes are independent, so do not exit coldboot operation */
- return 0;
-}
-
static int apb_poweroff(struct device *dev, void *data)
{
apb_ctrl_poweroff(dev);
if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
goto exit;
- /* First we want to make sure we power off everything
- * and then enter FW flashing state */
- device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
-
+ /*
+ * Here we only control SVC.
+ *
+ * In case of FW_FLASHING mode we do not want to control
+ * APBs, as in case of V2, SPI bus is shared between both
+ * the APBs. So let user chose which APB he wants to flash.
+ */
arche_platform_poweroff_seq(arche_pdata);
ret = arche_platform_fw_flashing_seq(arche_pdata);
if (ret)
goto exit;
-
- device_for_each_child(arche_pdata->dev, NULL, apb_fw_flashing_state);
} else {
dev_err(arche_pdata->dev, "unknown state\n");
ret = -EINVAL;