The recursive ownership support added in r321584 was unconditionally in
effect all the time -- whenever a given i2c slave device instance tried to
lock the i2c bus for exclusive use when it already owned the bus, the call
returned immediately without waiting. However, many i2c slave drivers use
bus ownership to enforce that only a single thread at a time can be using
the slave device. The recursive locking changes broke this use case.
Now there is a new flag, IIC_RECURSIVE, which can be mixed in with the
other flags passed to iicbus_acquire_bus() to allow drivers to indicate
when recursive locking is desired. Using the flag implies that the driver
is managing concurrent access to the device by different threads in some way.
This immediately fixes all existing i2c slave drivers except for the two
i2c RTC drivers which use the recursive locking feature; those will be
fixed in a followup commit.
RTC chips that have a control register bit for am/pm mode, the DS13xx series
uses one of the high bits in the hour register. Thus, when setting the time
in am/pm mode, the am/pm mode flag has to be ORed into the hour.
during startup. When a brand new chip leaves the factory, it is in a
special power-saving mode that disables most functions on the chip to
save battery power. The chip is stuck in this mode until the first write
to the time registers, which automatically clears the special power-saving
mode and starts the oscillator.
Also, the day-of-week register in this chip counts 1-7, not 0-6, so write
the values accordingly.
These changes are based on the patch submitted by Brian Scott, but I
elimated warnings since this condition is expected, and added some comments,
and so in general blame me for any mistakes.
PR: 223642
Mainly focus on files that use BSD 2-Clause license, however the tool I
was using misidentified many licenses so this was mostly a manual - error
prone - task.
The Software Package Data Exchange (SPDX) group provides a specification
to make it easier for automated tools to detect and summarize well known
opensource licenses. We are gradually adopting the specification, noting
that the tags are considered only advisory and do not, in any way,
superceed or replace the license texts.
Summary:
Existing code recognizes the mcp7941x RTC, but this RTC has an
enable bit at the same location as the "Clock Halt" bit on the ds1307, with an
opposite assertion (set == on, whereas CH set == clock stopped). Thus the
current code halts the clock, with no way to enable it.
Reviewed By: ian
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D12961
RTC-8583 is time-of-day clock used in some SOHO routers. This clock has
only 2 bits for year values, but thanks to user SRAM it's possible to save
year value and keep it up to date via driver code.
Tested on Planex_MZK-W300NAG (SoC is RT2880)
Submitted by: Hiroki Mori <yamori83@yahoo.co.jp>
Differential Revision: https://reviews.freebsd.org/D12833
stop, read, and write methods. Some controllers don't implement these
individual operations and have only a transfer method. In that case, we
should return an indication that the device is present but doesn't support
the method, as opposed to the kobj default error ENXIO which makes it
look like the whole device is missing. Userland tools such as i2c(8) can
use the differing return values to switch between the two different i2c
IO mechanisms.
setting up the timer fails, because on some types of chips that's the
first attempt to access the device. If the chip is missing/non-responsive
then you'd get a driver that attached and didn't register the rtc, with
no clue about why. On other chip types there are inits that come before
timer setup, and they already print messages about errors.
- Add FDT probe code.
- Do i2c transfers with exclusive bus ownership.
- Use config_intrhook_oneshot() to defer chip setup because some i2c
busses can't do transfers without interrupts.
- Add a detach() routine.
- Add to module build.
This driver supports only basic timekeeping functionality. It completely
replaces the ds133x driver. It can also replace the ds1374 driver, but that
will take a few other changes in MIPS code and config, and will be committed
separately. It does NOT replace the existing ds1307 driver, which provides
access to some of the extended features on the 1307 chip, such as controlling
the square wave output signal. If both ds1307 and ds13rtc drivers are
present, the ds1307 driver will outbid and win control of the device.
This driver can be configured with FDT data, or by using hints on non-FDT
systems. In addition to the standard hints for i2c devices, it requires
a "chiptype" string of the form "dallas,ds13xx" where 'xx' is the chip id
(i.e., the same format as FDT compat strings).
generic driver with minimal feature support for a large number of chips.
More featureful per-chip drivers might exist (especially out-of-tree) and
those should win the bidding even if they use BUS_PROBE_DEFAULT.
Don't enable the oscillator when it is found to be stopped at init time,
just let the first setting of valid time start it. But still report a dead
battery if it's stopped at init time.
Don't force the chip into 24hr mode, just cope with whatever mode it is
already in.
Schedule the clock_settime() callbacks to align the RTC clock to top of
second when setting it.
subr_rtc code, switch from CLOCKF_SETTIME_NO_TS to CLOCKF_SETTIME_NO_ADJ
so that we get fed a timestamp, but it's not adjusted to compensate for
inaccuracy in setting time.
between 12/24 hour mode. Also fix conversion between 12 and 24 hour mode.
It's not as easy as adding/subtracting 12, because the clock doesn't roll
over 11->0, it rolls over 12->1; 0 isn't a valid hour in AM/PM mode.
Don't enable the oscillator when it is found to be stopped at init time,
just let the first setting of valid time start it. But still report a dead
battery if it's stopped at init time.
Don't force the chip into 24hr mode, just cope with whatever mode it is
already in.
Align the RTC clock to top of second when setting it.
all the chips in the NXP PCA212x and PCA/PCF85xx series. In addition to
supporting more chips, this driver uses the countdown timer on the chips as
a fractional seconds counter, giving it a resolution of about 15 milliseconds.
Usually it is sufficient to use iicbus_transfer_excl(), or one of the
higher-level convenience functions that use it, to reserve the bus for the
duration of each register access. Occasionally it is important that a
series of accesses or read-modify-write operations must be done without any
other intervening access to the device, to prevent corrupting state.
Without support for nested request/release, slave device drivers would have
to stop using high-level convenience functions and resort to working with
arrays of iic_msg structs just for a few operations (often involving
one-time device setup or infrequent configuration changes).
The changes here appear large from a glance at the diff, but in fact they're
nearly trivial, and the large diff is because of changes in indentation and
the re-wrapping of comments caused by that. One notable change is that
iicbus_release_bus() now ignores the IICBUS_CALLBACK(IIC_RELEASE_BUS) return
value. The old error handling left the bus in a kind of limbo state where
it was still owned at the iicbus layer, but drivers rarely check the return
of the release call, and it's unclear what they would do to recover from an
error return anyway. No existing low-level drivers return any kind of error
from IIC_RELEASE_BUS except one EINVAL for "you don't own the bus", to which
the right response is probably to carry on with the process of releasing the
reference to the bus anyway.
on i2c devices, where the "register" can be any length.
Many (perhaps most) common i2c devices are organized as a collection of
(usually 1-byte-wide) registers, and are accessed by first writing a 1-byte
register index/offset number, then by reading or writing the data.
Generally there is an auto-increment feature so the when multiple bytes
are read or written, multiple contiguous registers are accessed.
Most existing slave device drivers allocate an array of iic_msg structures,
fill in all the transfer info, and invoke iicbus_transfer(). These new
functions commonize all that and reduce register access to a simple call
with a few arguments.
similar to "if (ticks > localvar+interval) {localvar=ticks; ...}" where
localvar is initialized to zero. Ticks is initialized to a negative value
since r278230, and that leads to these if statements never being true.
which is able to manipulate the clock and data lines directly.
When an i2c bus is hung by a slave device stuck in the middle of a
transaction that didn't complete properly, this function manipulates the
clock and data lines in a sequence known to reliably reset slave devices.
The most common cause of a hung i2c bus is a system reboot in the middle of
an i2c transfer (so it doesnt' happen often, but now there is a way other
than power cycling to recover from it).
nostop option is set, if a start was issued.
The nostop option doesn't mean "never issue a stop" it means "only issue
a stop after the last in a series of transfers". If the transfer ends
due to error, then that was the last transfer in the series, and a stop
is required.
Before this change, any error during a transfer when nostop is set would
effectively hang the bus, because sc->started would never get cleared,
and that caused all future calls to iicbus_start() to return an error
because it looked like the bus was already active. (Unrelated errors in
handling the nostop option, to be addressed separately, could lead to
this bus hang condition even on busses that don't set the nostop option.)
being overwritten, they are set only bits (cleared by hardware).
Disable the Acknowledge of the controller slave address. The slave mode is
not supported.
Make sure the interrupt flag bit is being cleared as recommended, add a
delay() _after_ clear the interrupt bit.
Sponsored by: Rubicon Communications, LLC (Netgate)
The constant was set to the correct value in r308242.
While there, fix iicsmb_bread() to not use a value of an out parameter
'count'.
MFC after: 3 weeks
X-MFC after: r308242
Summary:
The hardware does not expose a classic SMBus interface.
Instead it has a lower level interface that can express a far richer
I2C protocol than what smbus offers. However, the interface does not
provide a way to explicitly generate the I2C stop and start conditions.
It's only possible to request that the stop condition is generated
after transferring the next byte in either direction. So, at least
one data byte must always be transferred.
Thus, some I2C sequences are impossible to generate, e.g., an equivalent
of smbus quick command (<start>-<slave addr>-<r/w bit>-<stop>).
At the same time isl(4) and cyapa(4) are moved to iicbus and now they use
iicbus_transfer for communication. Previously they used smbus_trans()
interface that is not defined by the SMBus protocol and was implemented
only by ig4(4). In fact, that interface was impossible to implement
for the typical SMBus controllers like intpm(4) or ichsmb(4) where
a type of the SMBus command must be programmed.
The plan is to remove smbus_trans() and all its uses.
As an aside, the smbus_trans() method deviates from the standard,
but perhaps backwards, FreeBSD convention of using 8-bit slave
addresses (shifted by 1 bit to the left). The method expects
7-bit addresses.
There is a user facing consequence of this change.
A user must now provide device hints for isl and cyapa that specify an iicbus to use
and a slave address on it.
On Chromebook hardware where isl and cyapa devices are commonly found
it is also possible to use a new chromebook_platform(4) driver that
automatically configures isl and cyapa devices. There is no need to
provide the device hints in that case,
Right now smbus(4) driver tries to discover all slaves on the bus.
That is very dangerous. Fortunately, the probing code uses smbus_trans()
to do its job, so it is really enabled for ig4 only.
The plan is to remove that auto-probing code and smbus_trans().
Tested by: grembo, Matthias Apitz <guru@unixarea.de> (w/o
chromebook_platform)
Discussed with: grembo, imp
Reviewed by: wblock (docs)
MFC after: 1 month
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D8172
Previously the driver used more low level operations like iicbus_start
and iicbus_write. The problem is that those operations are not
implemented by iicbus(4) and the calls were effectively routed to
a driver to which the bus is attached.
But not all of the controllers implement such low level operations
while all of the drivers are expected to have iicbus_transfer.
While there fix incorrect implementation of iicsmb_bwrite and iicsmb_bread.
The former should send a byte count before the actual bytes, while the
latter should first receive the byte count and then receive the bytes.
I have tested only these commands:
- quick (r/w)
- send byte
- receive byte
- read byte
- write byte
MFC after: 1 month
Differential Revision: https://reviews.freebsd.org/D8170
'compat' can never be NULL, because the compatible check loop ends when
compat->ocd_str is NULL. This causes ds1307 to attach to any unclaimed i2c
device.
- Read interrupt properties at bus enumeration time and store
it into global mapping table.
- At bus_activate_resource() time, given mapping entry is resolved and
connected to real interrupt source. A copy of mapping entry is attached
to given resource.
- At bus_setup_intr() time, mapping entry stored in resource is used
for delivery of requested interrupt configuration.
- For MSI/MSIX interrupts, mapping entry is created within
pci_alloc_msi()/pci_alloc_msix() call.
- For legacy PCI interrupts, mapping entry must be created within
pcib_route_interrupt() by pcib driver itself.
Reviewed by: nwhitehorn, andrew
Differential Revision: https://reviews.freebsd.org/D7493
In some cases, the driver must handle given properties located in
specific OF subnode. Instead of creating duplicate set of function, add
'node' as argument to existing functions, defaulting it to device OF node.
MFC after: 3 weeks