Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156694650
D13039.id35890.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D13039.id35890.diff
View Options
Index: share/man/man9/bhnd.9
===================================================================
--- share/man/man9/bhnd.9
+++ share/man/man9/bhnd.9
@@ -266,9 +266,9 @@
.Fa "device_t dev" "bus_size_t offset" "const void *value" "u_int width"
.Fc
.Ft int
-.Fn bhnd_reset_hw "device_t dev" "uint16_t ioctl"
+.Fn bhnd_reset_hw "device_t dev" "uint16_t ioctl" "uint16_t reset_ioctl"
.Ft int
-.Fn bhnd_suspend_hw "device_t dev"
+.Fn bhnd_suspend_hw "device_t dev" "uint16_t ioctl"
.Ft bool
.Fn bhnd_is_hw_suspended "device_t dev"
.\"
@@ -1054,7 +1054,10 @@
.Fa dev
to a low power
.Dq RESET
-state.
+state, writing
+.Fa ioctl
+to the I/O control flags of
+.Fa dev .
The hardware may be brought out of this state using
.Fn bhnd_reset_hw .
.Pp
@@ -1062,10 +1065,14 @@
.Fn bhnd_reset_hw
function first transitions the device
.Fa dev
-to a low power RESET state, and then brings the device out of RESET, writing
+to a low power RESET state, writing
+.Fa ioctl_reset
+to the I/O control flags
+of
+.Fa dev ,
+and then brings the device out of RESET, writing
.Fa ioctl
-to the I/O control flags of
-.Fa dev .
+to the device's I/O control flags.
.Pp
The
.Fn bhnd_is_hw_suspended
Index: sys/dev/bhnd/bcma/bcma.c
===================================================================
--- sys/dev/bhnd/bcma/bcma.c
+++ sys/dev/bhnd/bcma/bcma.c
@@ -296,22 +296,22 @@
}
static int
-bcma_reset_hw(device_t dev, device_t child, uint16_t ioctl)
+bcma_reset_hw(device_t dev, device_t child, uint16_t ioctl,
+ uint16_t reset_ioctl)
{
- struct bcma_devinfo *dinfo;
- struct bhnd_core_pmu_info *pm;
- struct bhnd_resource *r;
- int error;
+ struct bcma_devinfo *dinfo;
+ struct bhnd_resource *r;
+ uint16_t clkflags;
+ int error;
if (device_get_parent(child) != dev)
return (EINVAL);
dinfo = device_get_ivars(child);
- pm = dinfo->pmu_info;
- /* We require exclusive control over BHND_IOCTL_CLK_EN and
- * BHND_IOCTL_CLK_FORCE. */
- if (ioctl & (BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE))
+ /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */
+ clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE;
+ if (ioctl & clkflags)
return (EINVAL);
/* Can't suspend the core without access to the agent registers */
@@ -319,7 +319,7 @@
return (ENODEV);
/* Place core into known RESET state */
- if ((error = BHND_BUS_SUSPEND_HW(dev, child)))
+ if ((error = bhnd_suspend_hw(child, reset_ioctl)))
return (error);
/*
@@ -329,9 +329,7 @@
* - Force clock distribution to ensure propagation throughout the
* core.
*/
- error = bhnd_write_ioctl(child,
- ioctl | BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE, UINT16_MAX);
- if (error)
+ if ((error = bhnd_write_ioctl(child, ioctl | clkflags, UINT16_MAX)))
return (error);
/* Bring the core out of reset */
@@ -347,11 +345,11 @@
}
static int
-bcma_suspend_hw(device_t dev, device_t child)
+bcma_suspend_hw(device_t dev, device_t child, uint16_t ioctl)
{
struct bcma_devinfo *dinfo;
struct bhnd_resource *r;
- uint32_t rst;
+ uint16_t clkflags;
int error;
if (device_get_parent(child) != dev)
@@ -359,6 +357,11 @@
dinfo = device_get_ivars(child);
+ /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */
+ clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE;
+ if (ioctl & clkflags)
+ return (EINVAL);
+
/* Can't suspend the core without access to the agent registers */
if ((r = dinfo->res_agent) == NULL)
return (ENODEV);
@@ -367,17 +370,12 @@
if ((error = bcma_dmp_wait_reset(child, dinfo)))
return (error);
- /* Already in reset? */
- rst = bhnd_bus_read_4(r, BCMA_DMP_RESETCTRL);
- if (rst & BCMA_DMP_RC_RESET)
- return (0);
-
- /* Put core into reset */
+ /* Put core into reset (if not already in reset) */
if ((error = bcma_dmp_write_reset(child, dinfo, BCMA_DMP_RC_RESET)))
return (error);
- /* Clear core flags */
- if ((error = bhnd_write_ioctl(child, 0x0, UINT16_MAX)))
+ /* Write core flags (and clear CLK_EN/CLK_FORCE) */
+ if ((error = bhnd_write_ioctl(child, ioctl, ~clkflags)))
return (error);
return (0);
Index: sys/dev/bhnd/bcma/bcma_subr.c
===================================================================
--- sys/dev/bhnd/bcma/bcma_subr.c
+++ sys/dev/bhnd/bcma/bcma_subr.c
@@ -594,9 +594,16 @@
int
bcma_dmp_write_reset(device_t child, struct bcma_devinfo *dinfo, uint32_t value)
{
+ uint32_t rst;
+
if (dinfo->res_agent == NULL)
return (ENODEV);
+ /* Already in requested reset state? */
+ rst = bhnd_bus_read_4(dinfo->res_agent, BCMA_DMP_RESETCTRL);
+ if (rst == value)
+ return (0);
+
bhnd_bus_write_4(dinfo->res_agent, BCMA_DMP_RESETCTRL, value);
bhnd_bus_read_4(dinfo->res_agent, BCMA_DMP_RESETCTRL); /* read-back */
DELAY(10);
Index: sys/dev/bhnd/bhnd.h
===================================================================
--- sys/dev/bhnd/bhnd.h
+++ sys/dev/bhnd/bhnd.h
@@ -818,23 +818,27 @@
}
/**
- * Place the bhnd(4) device's hardware into a reset state, and then bring the
- * hardware out of reset with BHND_IOCTL_CLK_EN and @p ioctl flags set.
+ * Place the bhnd(4) device's hardware into a low-power RESET state with
+ * the @p reset_ioctl I/O control flags set, and then bring the hardware out of
+ * RESET with the @p ioctl I/O control flags set.
*
- * Any clock or resource PMU requests previously made by @p dev will be
+ * Any clock or resource PMU requests previously made by @p child will be
* invalidated.
*
* @param dev The device to be reset.
- * @param ioctl Device-specific core ioctl flags to be supplied on reset
- * (see BHND_IOCTL_*).
+ * @param ioctl Device-specific I/O control flags to be set when bringing
+ * the core out of its RESET state (see BHND_IOCTL_*).
+ * @param reset_ioctl Device-specific I/O control flags to be set when placing
+ * the core into its RESET state.
*
* @retval 0 success
* @retval non-zero error
*/
static inline int
-bhnd_reset_hw(device_t dev, uint16_t ioctl)
+bhnd_reset_hw(device_t dev, uint16_t ioctl, uint16_t reset_ioctl)
{
- return (BHND_BUS_RESET_HW(device_get_parent(dev), dev, ioctl));
+ return (BHND_BUS_RESET_HW(device_get_parent(dev), dev, ioctl,
+ reset_ioctl));
}
/**
@@ -851,9 +855,9 @@
* @retval non-zero error
*/
static inline int
-bhnd_suspend_hw(device_t dev)
+bhnd_suspend_hw(device_t dev, uint16_t ioctl)
{
- return (BHND_BUS_SUSPEND_HW(device_get_parent(dev), dev));
+ return (BHND_BUS_SUSPEND_HW(device_get_parent(dev), dev, ioctl));
}
/**
Index: sys/dev/bhnd/bhnd_bus_if.m
===================================================================
--- sys/dev/bhnd/bhnd_bus_if.m
+++ sys/dev/bhnd/bhnd_bus_if.m
@@ -96,7 +96,8 @@
}
static int
- bhnd_bus_null_reset_hw(device_t dev, device_t child, uint16_t ioctl)
+ bhnd_bus_null_reset_hw(device_t dev, device_t child, uint16_t ioctl,
+ uint16_t reset_ioctl)
{
panic("bhnd_bus_reset_hw unimplemented");
}
@@ -624,16 +625,19 @@
} DEFAULT bhnd_bus_null_is_hw_suspended;
/**
- * Place the bhnd(4) device's hardware into a reset state, and then bring the
- * hardware out of reset with BHND_IOCTL_CLK_EN and @p ioctl flags set.
+ * Place the bhnd(4) device's hardware into a low-power RESET state with
+ * the @p reset_ioctl I/O control flags set, and then bring the hardware out of
+ * RESET with the @p ioctl I/O control flags set.
*
* Any clock or resource PMU requests previously made by @p child will be
* invalidated.
*
* @param dev The bhnd bus parent of @p child.
* @param child The device to be reset.
- * @param ioctl Device-specific core ioctl flags to be supplied on reset
- * (see BHND_IOCTL_*).
+ * @param ioctl Device-specific I/O control flags to be set when bringing
+ * the core out of its RESET state (see BHND_IOCTL_*).
+ * @param reset_ioctl Device-specific I/O control flags to be set when placing
+ * the core into its RESET state.
*
* @retval 0 success
* @retval non-zero error
@@ -642,18 +646,21 @@
device_t dev;
device_t child;
uint16_t ioctl;
+ uint16_t reset_ioctl;
} DEFAULT bhnd_bus_null_reset_hw;
/**
- * Suspend @p child's hardware in a low-power reset state.
+ * Suspend @p child's hardware in a low-power RESET state.
*
* Any clock or resource PMU requests previously made by @p dev will be
* invalidated.
*
- * The hardware may be brought out of reset via bhnd_reset_hw().
+ * The hardware may be brought out of RESET via bhnd_reset_hw().
*
* @param dev The bhnd bus parent of @p child.
* @param dev The device to be suspended.
+ * @param ioctl Device-specific I/O control flags to be set when placing
+ * the core into its RESET state (see BHND_IOCTL_*).
*
* @retval 0 success
* @retval non-zero error
@@ -661,6 +668,7 @@
METHOD int suspend_hw {
device_t dev;
device_t child;
+ uint16_t ioctl;
} DEFAULT bhnd_bus_null_suspend_hw;
/**
Index: sys/dev/bhnd/cores/usb/bhnd_usb.c
===================================================================
--- sys/dev/bhnd/cores/usb/bhnd_usb.c
+++ sys/dev/bhnd/cores/usb/bhnd_usb.c
@@ -98,7 +98,7 @@
sc = device_get_softc(dev);
- bhnd_reset_hw(dev, 0);
+ bhnd_reset_hw(dev, 0, 0);
/*
* Allocate the resources which the parent bus has already
Index: sys/dev/bhnd/siba/siba.c
===================================================================
--- sys/dev/bhnd/siba/siba.c
+++ sys/dev/bhnd/siba/siba.c
@@ -603,8 +603,9 @@
ts_mask = (mask << SIBA_TML_SICF_SHIFT) & SIBA_TML_SICF_MASK;
ts_low = (value << SIBA_TML_SICF_SHIFT) & ts_mask;
- return (siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
- ts_low, ts_mask));
+ siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
+ ts_low, ts_mask);
+ return (0);
}
static bool
@@ -626,6 +627,10 @@
if (ts_low & SIBA_TML_RESET)
return (true);
+ /* Is target reject enabled? */
+ if (ts_low & SIBA_TML_REJ_MASK)
+ return (true);
+
/* Is core clocked? */
ioctl = SIBA_REG_GET(ts_low, TML_SICF);
if (!(ioctl & BHND_IOCTL_CLK_EN))
@@ -635,11 +640,13 @@
}
static int
-siba_reset_hw(device_t dev, device_t child, uint16_t ioctl)
+siba_reset_hw(device_t dev, device_t child, uint16_t ioctl,
+ uint16_t reset_ioctl)
{
struct siba_devinfo *dinfo;
struct bhnd_resource *r;
uint32_t ts_low, imstate;
+ uint16_t clkflags;
int error;
if (device_get_parent(child) != dev)
@@ -651,66 +658,60 @@
if ((r = dinfo->cfg_res[0]) == NULL)
return (ENODEV);
- /* We require exclusive control over BHND_IOCTL_CLK_EN and
- * BHND_IOCTL_CLK_FORCE. */
- if (ioctl & (BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE))
+ /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */
+ clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE;
+ if (ioctl & clkflags)
return (EINVAL);
/* Place core into known RESET state */
- if ((error = BHND_BUS_SUSPEND_HW(dev, child)))
+ if ((error = bhnd_suspend_hw(child, reset_ioctl)))
return (error);
- /* Leaving the core in reset, set the caller's IOCTL flags and
- * enable the core's clocks. */
- ts_low = (ioctl | BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE) <<
- SIBA_TML_SICF_SHIFT;
- error = siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
- ts_low, SIBA_TML_SICF_MASK);
- if (error)
- return (error);
+ /* Set RESET, clear REJ, set the caller's IOCTL flags, and
+ * force clocks to ensure the signal propagates throughout the
+ * core. */
+ ts_low = SIBA_TML_RESET |
+ (ioctl << SIBA_TML_SICF_SHIFT) |
+ (BHND_IOCTL_CLK_EN << SIBA_TML_SICF_SHIFT) |
+ (BHND_IOCTL_CLK_FORCE << SIBA_TML_SICF_SHIFT);
+
+ siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
+ ts_low, UINT32_MAX);
/* Clear any target errors */
if (bhnd_bus_read_4(r, SIBA_CFG0_TMSTATEHIGH) & SIBA_TMH_SERR) {
- error = siba_write_target_state(child, dinfo,
- SIBA_CFG0_TMSTATEHIGH, 0, SIBA_TMH_SERR);
- if (error)
- return (error);
+ siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATEHIGH,
+ 0x0, SIBA_TMH_SERR);
}
/* Clear any initiator errors */
imstate = bhnd_bus_read_4(r, SIBA_CFG0_IMSTATE);
if (imstate & (SIBA_IM_IBE|SIBA_IM_TO)) {
- error = siba_write_target_state(child, dinfo, SIBA_CFG0_IMSTATE,
- 0, SIBA_IM_IBE|SIBA_IM_TO);
- if (error)
- return (error);
+ siba_write_target_state(child, dinfo, SIBA_CFG0_IMSTATE, 0x0,
+ SIBA_IM_IBE|SIBA_IM_TO);
}
/* Release from RESET while leaving clocks forced, ensuring the
* signal propagates throughout the core */
- error = siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
- 0x0, SIBA_TML_RESET);
- if (error)
- return (error);
+ siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW, 0x0,
+ SIBA_TML_RESET);
/* The core should now be active; we can clear the BHND_IOCTL_CLK_FORCE
* bit and allow the core to manage clock gating. */
- error = siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
- 0x0, (BHND_IOCTL_CLK_FORCE << SIBA_TML_SICF_SHIFT));
- if (error)
- return (error);
+ siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW, 0x0,
+ (BHND_IOCTL_CLK_FORCE << SIBA_TML_SICF_SHIFT));
return (0);
}
static int
-siba_suspend_hw(device_t dev, device_t child)
+siba_suspend_hw(device_t dev, device_t child, uint16_t ioctl)
{
struct siba_softc *sc;
struct siba_devinfo *dinfo;
struct bhnd_resource *r;
- uint32_t idl, ts_low;
- uint16_t ioctl;
+ uint32_t idl, ts_low, ts_mask;
+ uint16_t cflags, clkflags;
int error;
if (device_get_parent(child) != dev)
@@ -723,30 +724,37 @@
if ((r = dinfo->cfg_res[0]) == NULL)
return (ENODEV);
+ /* We require exclusive control over BHND_IOCTL_CLK_(EN|FORCE) */
+ clkflags = BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE;
+ if (ioctl & clkflags)
+ return (EINVAL);
+
/* Already in RESET? */
ts_low = bhnd_bus_read_4(r, SIBA_CFG0_TMSTATELOW);
- if (ts_low & SIBA_TML_RESET) {
- /* Clear IOCTL flags, ensuring the clock is disabled */
- return (siba_write_target_state(child, dinfo,
- SIBA_CFG0_TMSTATELOW, 0x0, SIBA_TML_SICF_MASK));
-
+ if (ts_low & SIBA_TML_RESET)
return (0);
- }
- /* If clocks are already disabled, we can put the core directly
- * into RESET */
- ioctl = SIBA_REG_GET(ts_low, TML_SICF);
- if (!(ioctl & BHND_IOCTL_CLK_EN)) {
- /* Set RESET and clear IOCTL flags */
- return (siba_write_target_state(child, dinfo,
- SIBA_CFG0_TMSTATELOW,
- SIBA_TML_RESET,
- SIBA_TML_RESET | SIBA_TML_SICF_MASK));
+ /* If clocks are already disabled, we can place the core directly
+ * into RESET|REJ while setting the caller's IOCTL flags. */
+ cflags = SIBA_REG_GET(ts_low, TML_SICF);
+ if (!(cflags & BHND_IOCTL_CLK_EN)) {
+ ts_low = SIBA_TML_RESET | SIBA_TML_REJ |
+ (ioctl << SIBA_TML_SICF_SHIFT);
+ ts_mask = SIBA_TML_RESET | SIBA_TML_REJ | SIBA_TML_SICF_MASK;
+
+ siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
+ ts_low, ts_mask);
+ return (0);
}
- /* Reject any further target backplane transactions */
- error = siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
+ /* Reject further transactions reaching this core */
+ siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
SIBA_TML_REJ, SIBA_TML_REJ);
+
+ /* Wait for transaction busy flag to clear for all transactions
+ * initiated by this core */
+ error = siba_wait_target_state(child, dinfo, SIBA_CFG0_TMSTATEHIGH,
+ 0x0, SIBA_TMH_BUSY, 100000);
if (error)
return (error);
@@ -754,44 +762,47 @@
* transactions too. */
idl = bhnd_bus_read_4(r, SIBA_CFG0_IDLOW);
if (idl & SIBA_IDL_INIT) {
- error = siba_write_target_state(child, dinfo, SIBA_CFG0_IMSTATE,
+ /* Reject further initiator transactions */
+ siba_write_target_state(child, dinfo, SIBA_CFG0_IMSTATE,
SIBA_IM_RJ, SIBA_IM_RJ);
+
+ /* Wait for initiator busy flag to clear */
+ error = siba_wait_target_state(child, dinfo, SIBA_CFG0_IMSTATE,
+ 0x0, SIBA_IM_BY, 100000);
if (error)
return (error);
}
- /* Put the core into RESET|REJECT, forcing clocks to ensure the RESET
- * signal propagates throughout the core, leaving REJECT asserted. */
- ts_low = SIBA_TML_RESET;
- ts_low |= (BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE) <<
- SIBA_TML_SICF_SHIFT;
-
- error = siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
- ts_low, ts_low);
+ /* Put the core into RESET, set the caller's IOCTL flags, and
+ * force clocks to ensure the RESET signal propagates throughout the
+ * core. */
+ ts_low = SIBA_TML_RESET |
+ (ioctl << SIBA_TML_SICF_SHIFT) |
+ (BHND_IOCTL_CLK_EN << SIBA_TML_SICF_SHIFT) |
+ (BHND_IOCTL_CLK_FORCE << SIBA_TML_SICF_SHIFT);
+ ts_mask = SIBA_TML_RESET |
+ SIBA_TML_SICF_MASK;
+
+ siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW, ts_low,
+ ts_mask);
if (error)
return (error);
/* Give RESET ample time */
DELAY(10);
- /* Leaving core in reset, disable all clocks, clear REJ flags and
- * IOCTL state */
- error = siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW,
- SIBA_TML_RESET,
- SIBA_TML_RESET | SIBA_TML_REJ | SIBA_TML_SICF_MASK);
- if (error)
- return (error);
-
/* Clear previously asserted initiator reject */
if (idl & SIBA_IDL_INIT) {
- error = siba_write_target_state(child, dinfo, SIBA_CFG0_IMSTATE,
- 0, SIBA_IM_RJ);
- if (error)
- return (error);
+ siba_write_target_state(child, dinfo, SIBA_CFG0_IMSTATE, 0x0,
+ SIBA_IM_RJ);
}
+ /* Disable all clocks, leaving RESET and REJ asserted */
+ siba_write_target_state(child, dinfo, SIBA_CFG0_TMSTATELOW, 0x0,
+ (BHND_IOCTL_CLK_EN | BHND_IOCTL_CLK_FORCE) << SIBA_TML_SICF_SHIFT);
+
/*
- * Core is now in RESET, with clocks disabled and REJ not asserted.
+ * Core is now in RESET.
*
* If the core holds any PWRCTL clock reservations, we need to release
* those now. This emulates the standard bhnd(4) PMU behavior of RESET
Index: sys/dev/bhnd/siba/siba_subr.c
===================================================================
--- sys/dev/bhnd/siba/siba_subr.c
+++ sys/dev/bhnd/siba/siba_subr.c
@@ -624,83 +624,73 @@
}
/**
- * Write @p value to @p dev's CFG0 target/initiator state register and
- * wait for completion.
+ * Write @p value to @p dev's CFG0 target/initiator state register, performing
+ * required read-back and waiting for completion.
*
* @param dev The siba(4) child device.
- * @param reg The state register to write (e.g. SIBA_CFG0_TMSTATELOW,
- * SIBA_CFG0_IMSTATE)
+ * @param reg The CFG0 state register to write (e.g. SIBA_CFG0_TMSTATELOW,
+ * SIBA_CFG0_IMSTATE)
* @param value The value to write to @p reg.
* @param mask The mask of bits to be included from @p value.
- *
- * @retval 0 success.
- * @retval ENODEV if SIBA_CFG0 is not mapped by @p dinfo.
- * @retval ETIMEDOUT if a timeout occurs prior to SIBA_TMH_BUSY clearing.
*/
-int
+void
siba_write_target_state(device_t dev, struct siba_devinfo *dinfo,
bus_size_t reg, uint32_t value, uint32_t mask)
{
struct bhnd_resource *r;
uint32_t rval;
- /* Must have a CFG0 block */
- if ((r = dinfo->cfg_res[0]) == NULL)
- return (ENODEV);
-
- /* Verify the register offset falls within CFG register block */
- if (reg > SIBA_CFG_SIZE-4)
- return (EFAULT);
-
- for (int i = 0; i < 300; i += 10) {
- rval = bhnd_bus_read_4(r, reg);
- rval &= ~mask;
- rval |= (value & mask);
-
- bhnd_bus_write_4(r, reg, rval);
- bhnd_bus_read_4(r, reg); /* read-back */
- DELAY(1);
+ r = dinfo->cfg_res[0];
- /* If the write has completed, wait for target busy state
- * to clear */
- rval = bhnd_bus_read_4(r, reg);
- if ((rval & mask) == (value & mask))
- return (siba_wait_target_busy(dev, dinfo, 100000));
+ KASSERT(r != NULL, ("%s missing CFG0 mapping",
+ device_get_nameunit(dev)));
+ KASSERT(reg <= SIBA_CFG_SIZE-4, ("%s invalid CFG0 register offset %#jx",
+ device_get_nameunit(dev), (uintmax_t)reg));
- DELAY(10);
- }
+ rval = bhnd_bus_read_4(r, reg);
+ rval &= ~mask;
+ rval |= (value & mask);
- return (ETIMEDOUT);
+ bhnd_bus_write_4(r, reg, rval);
+ bhnd_bus_read_4(r, reg); /* read-back */
+ DELAY(1);
}
/**
- * Spin for up to @p usec waiting for SIBA_TMH_BUSY to clear in
- * @p dev's SIBA_CFG0_TMSTATEHIGH register.
+ * Spin for up to @p usec waiting for @p dev's CFG0 target/initiator state
+ * register value to be equal to @p value after applying @p mask bits to both
+ * values.
*
* @param dev The siba(4) child device to wait on.
* @param dinfo The @p dev's device info
+ * @param reg The state register to read (e.g. SIBA_CFG0_TMSTATEHIGH,
+ * SIBA_CFG0_IMSTATE)
+ * @param value The value against which @p reg will be compared.
+ * @param mask The mask to be applied when comparing @p value with @p reg.
+ * @param usec The maximum number of microseconds to wait for completion.
*
* @retval 0 if SIBA_TMH_BUSY is cleared prior to the @p usec timeout.
* @retval ENODEV if SIBA_CFG0 is not mapped by @p dinfo.
- * @retval ETIMEDOUT if a timeout occurs prior to SIBA_TMH_BUSY clearing.
+ * @retval ETIMEDOUT if a timeout occurs.
*/
int
-siba_wait_target_busy(device_t dev, struct siba_devinfo *dinfo, int usec)
+siba_wait_target_state(device_t dev, struct siba_devinfo *dinfo, bus_size_t reg,
+ uint32_t value, uint32_t mask, u_int usec)
{
struct bhnd_resource *r;
- uint32_t ts_high;
+ uint32_t rval;
if ((r = dinfo->cfg_res[0]) == NULL)
return (ENODEV);
+ value &= mask;
for (int i = 0; i < usec; i += 10) {
- ts_high = bhnd_bus_read_4(r, SIBA_CFG0_TMSTATEHIGH);
- if (!(ts_high & SIBA_TMH_BUSY))
+ rval = bhnd_bus_read_4(r, reg);
+ if ((rval & mask) == value)
return (0);
DELAY(10);
}
- device_printf(dev, "SIBA_TMH_BUSY wait timeout\n");
return (ETIMEDOUT);
}
Index: sys/dev/bhnd/siba/sibavar.h
===================================================================
--- sys/dev/bhnd/siba/sibavar.h
+++ sys/dev/bhnd/siba/sibavar.h
@@ -117,11 +117,12 @@
int siba_parse_admatch(uint32_t am, uint32_t *addr,
uint32_t *size);
-int siba_write_target_state(device_t dev,
+void siba_write_target_state(device_t dev,
struct siba_devinfo *dinfo, bus_size_t reg,
uint32_t value, uint32_t mask);
-int siba_wait_target_busy(device_t child,
- struct siba_devinfo *dinfo, int usec);
+int siba_wait_target_state(device_t dev,
+ struct siba_devinfo *dinfo, bus_size_t reg,
+ uint32_t value, uint32_t mask, u_int usec);
/* Sonics configuration register blocks */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, May 16, 5:57 PM (19 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33142724
Default Alt Text
D13039.id35890.diff (21 KB)
Attached To
Mode
D13039: bhnd(4): Implement missing support for specifying I/O control flags during core reset.
Attached
Detach File
Event Timeline
Log In to Comment