Commit 0ea7d706 authored by Lee Jones's avatar Lee Jones Committed by Brian Norris
Browse files

mtd: st_spi_fsm: Add a check to if the chip can handle an SoC reset



Based on information we can obtain though platform specific data and/or
chip capabilities we are able to determine whether or not we can handle
a SoC reset or not. To find out why this is important please read the
comment provided in the patch.

Acked-by Angus Clark <angus.clark@st.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
parent 88cccb89
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -210,6 +210,8 @@ struct stfsm {

	uint32_t                fifo_dir_delay;
	bool                    booted_from_spi;
	bool                    reset_signal;
	bool                    reset_por;
};

struct stfsm_seq {
@@ -521,6 +523,40 @@ static void stfsm_read_fifo(struct stfsm *fsm, uint32_t *buf,
	}
}

/*
 * SoC reset on 'boot-from-spi' systems
 *
 * Certain modes of operation cause the Flash device to enter a particular state
 * for a period of time (e.g. 'Erase Sector', 'Quad Enable', and 'Enter 32-bit
 * Addr' commands).  On boot-from-spi systems, it is important to consider what
 * happens if a warm reset occurs during this period.  The SPIBoot controller
 * assumes that Flash device is in its default reset state, 24-bit address mode,
 * and ready to accept commands.  This can be achieved using some form of
 * on-board logic/controller to force a device POR in response to a SoC-level
 * reset or by making use of the device reset signal if available (limited
 * number of devices only).
 *
 * Failure to take such precautions can cause problems following a warm reset.
 * For some operations (e.g. ERASE), there is little that can be done.  For
 * other modes of operation (e.g. 32-bit addressing), options are often
 * available that can help minimise the window in which a reset could cause a
 * problem.
 *
 */
static bool stfsm_can_handle_soc_reset(struct stfsm *fsm)
{
	/* Reset signal is available on the board and supported by the device */
	if (fsm->reset_signal && fsm->info->flags & FLASH_FLAG_RESET)
		return true;

	/* Board-level logic forces a power-on-reset */
	if (fsm->reset_por)
		return true;

	/* Reset is not properly handled and may result in failure to reboot */
	return false;
}

/* Configure 'addr_cfg' according to addressing mode */
static void stfsm_prepare_erasesec_seq(struct stfsm *fsm,
				       struct stfsm_seq *seq)
@@ -786,6 +822,10 @@ static void stfsm_fetch_platform_configs(struct platform_device *pdev)
	if (IS_ERR(regmap))
		goto boot_device_fail;

	fsm->reset_signal = of_property_read_bool(np, "st,reset-signal");

	fsm->reset_por = of_property_read_bool(np, "st,reset-por");

	/* Where in the syscon the boot device information lives */
	ret = of_property_read_u32(np, "st,boot-device-reg", &boot_device_reg);
	if (ret)