New 1-Wire bus implementation. 1-Wire controller is abstracted, though
only gpiobus configured via FDT is supported. Bus enumeration is supported. Devices are created for each device found. 1-Wire temperature controllers are supported, but other drivers could be written. Temperatures are polled and reported via a sysctl. Errors are reported via sysctl counters. Mis-wired bus detection is included for more trouble shooting. See ow(4), owc(4) and ow_temp(4) for details of what's supported and known issues. This has been tested on Raspberry Pi-B, Pi2 and Beagle Bone Black with up to 7 devices. Differential Revision: https://reviews.freebsd.org/D2956 Relnotes: yes MFC after: 2 weeks Reviewed by: loos@ (with many insightful comments)
This commit is contained in:
parent
01da73abdc
commit
ae1f3df434
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=287225
@ -379,6 +379,9 @@ MAN= aac.4 \
|
||||
oce.4 \
|
||||
ohci.4 \
|
||||
orm.4 \
|
||||
ow.4 \
|
||||
ow_temp.4 \
|
||||
owc.4 \
|
||||
${_padlock.4} \
|
||||
pass.4 \
|
||||
patm.4 \
|
||||
@ -667,6 +670,7 @@ MLINKS+=nge.4 if_nge.4
|
||||
MLINKS+=${_ntb.4} ${_if_ntb.4} \
|
||||
${_ntb.4} ${_ntb_hw.4}
|
||||
MLINKS+=${_nxge.4} ${_if_nxge.4}
|
||||
MLINKS+=ow.4 onewire.4
|
||||
MLINKS+=patm.4 if_patm.4
|
||||
MLINKS+=pccbb.4 cbb.4
|
||||
MLINKS+=pcm.4 snd.4 \
|
||||
|
60
share/man/man4/ow.4
Normal file
60
share/man/man4/ow.4
Normal file
@ -0,0 +1,60 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2015 M. Warner Losh
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 20, 2015
|
||||
.Dt OW 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ow
|
||||
.Nd Dallas Semiconductor 1-Wire bus
|
||||
.Sh SYNOPSIS
|
||||
.Cd device ow
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
module implements the Dallas Semiconductor 1-Wire bus.
|
||||
It attaches to the
|
||||
.Xr owc 4
|
||||
driver, which implements the low-level signaling of the
|
||||
1-Wire bus.
|
||||
.Sh SEE ALSO
|
||||
.Xr ow_temp 4 ,
|
||||
.Xr owc 4 ,
|
||||
.Xr owll 9 ,
|
||||
.Xr own 9
|
||||
.Sh LEGAL
|
||||
.Tn 1-Wire
|
||||
is a registered trademark of Maxim Integrated Products, Inc.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver first appeared in
|
||||
.Fx 11.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were written by
|
||||
.An Warner Losh .
|
155
share/man/man4/ow_temp.4
Normal file
155
share/man/man4/ow_temp.4
Normal file
@ -0,0 +1,155 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2015 M. Warner Losh
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 20, 2015
|
||||
.Dt OW_TEMP 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ow_temp
|
||||
.Nd Dallas Semiconductor 1-Wire Temperature sensor
|
||||
.Sh SYNOPSIS
|
||||
.Cd device ow_temp
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
module supports many of the 1-Wire temperature sensors.
|
||||
.Pp
|
||||
The sensor is read periodically and the results returned via a
|
||||
.Xr sysctl 3
|
||||
as described below.
|
||||
.Sh HARDWARE
|
||||
These temperature sensors are supported by the
|
||||
.Nm
|
||||
driver:
|
||||
.Bl -tag -width MAX31820 -compact
|
||||
.It DS1820
|
||||
1-Wire Digital Thermometer
|
||||
.It DS18S20
|
||||
High-Precision 1-Wire Digital Thermometer
|
||||
.It DS18B20
|
||||
Programmable Resolution 1-Wire Digital Thermometer
|
||||
.It DS1822
|
||||
Econo 1-Wire Digital Thermometer
|
||||
.It DS1825
|
||||
Programmable Resolution 1-Wire Digital Thermometer with 4-bit ID
|
||||
.It MAX31820
|
||||
1-Wire, Parasite-Power, Ambient Temperature Sensor
|
||||
.El
|
||||
.Pp
|
||||
The driver supports Family codes 0x10, 0x22, 0x28, and 0x3b.
|
||||
.Sh SYSCTL
|
||||
The
|
||||
.Nm
|
||||
driver reports data via
|
||||
.Xr sysctl 8
|
||||
entries in the device's node in the
|
||||
.Xr sysctl 8
|
||||
tree:
|
||||
.Bl -tag -width xxxxxxxxxx
|
||||
.It temperature
|
||||
The last temperature read, in milli-Kelvin.
|
||||
.It badcrc
|
||||
The number of CRC errors in reading the temperature form the
|
||||
device.
|
||||
Some CRC errors are to be expected.
|
||||
High rates of CRC errors, however, generally indicate a noisy
|
||||
environment, cabling issues, or too many devices on the bus.
|
||||
.It badread
|
||||
The number of times a non-CRC error was encountered reading the temperature
|
||||
from the card.
|
||||
This type of error is very rare.
|
||||
.It reading_interval
|
||||
The time, in ticks, between successive reads of the sensor.
|
||||
.It parasite
|
||||
This item is non-zero when the device is connected using its parasitic
|
||||
power mode.
|
||||
It can also indicate a wiring error.
|
||||
.El
|
||||
.Pp
|
||||
Temperatures are reported in milli-Kelvin, even though the absolute
|
||||
accuracy is around 0.2 degrees for the good devices and around 1
|
||||
degree for cheaper devices.
|
||||
The devices report in steps of 0.0625 degrees.
|
||||
The driver preserves the precision of the device's measurements
|
||||
in its
|
||||
.Xr sysctl 8
|
||||
reports.
|
||||
These devices often have a much higher relative accuracy and
|
||||
repeatability than their absolute accuracy.
|
||||
This makes them well suited for control loops that strive for
|
||||
stability and become possible if the full precision is preserved.
|
||||
.Sh SEE ALSO
|
||||
.Xr ow 4 ,
|
||||
.Xr owc 4 ,
|
||||
.Xr sysctl 8 ,
|
||||
.Xr owll 9 ,
|
||||
.Xr own 9
|
||||
.Sh LEGAL
|
||||
.Tn 1-Wire
|
||||
is a registered trademark of Maxim Integrated Products, Inc.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver first appeared in
|
||||
.Fx 11.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were written by
|
||||
.An Warner Losh .
|
||||
.Sh BUGS
|
||||
The parasitic mode of the devices does not work.
|
||||
It requires support from the
|
||||
.Xr owc 4
|
||||
driver that is unimplemented.
|
||||
.Pp
|
||||
The ID bits from the
|
||||
.Em DS1825
|
||||
are not recognized or reported.
|
||||
.Pp
|
||||
The type of the device is not reported via
|
||||
.Xr sysctl 8 .
|
||||
.Pp
|
||||
Alarm mode is not supported.
|
||||
It is not possible to set the low and high alarm temperatures.
|
||||
.Pp
|
||||
There is no way to write to the EEPROM.
|
||||
.Pp
|
||||
.Dq Convert Temperature
|
||||
requests are sent directly to the device.
|
||||
There is no way to use the broadcast ability of the 1-Wire bus to do
|
||||
all the conversions in parallel.
|
||||
.Pp
|
||||
It is not possible to set the precision on those devices that support
|
||||
it.
|
||||
.Pp
|
||||
The time to convert is fixed at 1 second, even though some devices are
|
||||
faster.
|
||||
.Pp
|
||||
There is no character device to supply a stream of readings to a
|
||||
program.
|
||||
Programs interested in the temperature must poll the sysctl to get the
|
||||
temperature.
|
95
share/man/man4/owc.4
Normal file
95
share/man/man4/owc.4
Normal file
@ -0,0 +1,95 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2015 M. Warner Losh
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 20, 2015
|
||||
.Dt OWC 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm owc
|
||||
.Nd Dallas Semiconductor 1-Wire Controller
|
||||
.Sh SYNOPSIS
|
||||
.Cd device owc
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
module implements Dallas Semiconductor 1-Wire signaling.
|
||||
It attaches the
|
||||
.Xr ow 4
|
||||
driver 1-Wire bus protocol.
|
||||
The
|
||||
.Nm
|
||||
device implements the Link Layer of the 1-Wire bus protocol stack.
|
||||
.Pp
|
||||
Bit banging a pin on a
|
||||
.Xr gpiobus 4
|
||||
is the only supported controller.
|
||||
Both standard and overdrive transfer timings are implemented.
|
||||
Strong pull-up functionality needed to support parasitic mode is not
|
||||
implemented.
|
||||
.Pp
|
||||
To enable 1-Wire for FDT systems requires modifying the DTS for your
|
||||
board to add something like:
|
||||
.Bd -literal
|
||||
/ {
|
||||
...
|
||||
onewire {
|
||||
compatible = "w1-gpio";
|
||||
gpios = <&gpio 4 1>;
|
||||
};
|
||||
...
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
The gpios property describes the GPIO pin the 1-Wire bus is connected
|
||||
to.
|
||||
For more details about the
|
||||
.Va gpios
|
||||
property, please consult
|
||||
.Pa /usr/src/sys/boot/fdt/dts/bindings-gpio.txt .
|
||||
.Sh SEE ALSO
|
||||
.Xr gpiobus 4 ,
|
||||
.Xr ow 4 ,
|
||||
.Xr ow_temp 4 ,
|
||||
.Xr owll 9 ,
|
||||
.Xr own 9
|
||||
.Sh LEGAL
|
||||
.Tn 1-Wire
|
||||
is a registered trademark of Maxim Integrated Products, Inc.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver first appeared in
|
||||
.Fx 11.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were written by
|
||||
.An Warner Losh .
|
||||
.Sh CAVEATS
|
||||
The gpio driver implements timing by busy waiting, which can cause a
|
||||
high load on slower systems.
|
||||
.Sh BUGS
|
||||
Overdrive mode has not actually been tested.
|
@ -190,6 +190,8 @@ MAN= accept_filter.9 \
|
||||
netisr.9 \
|
||||
nv.9 \
|
||||
osd.9 \
|
||||
owll.9 \
|
||||
own.9 \
|
||||
panic.9 \
|
||||
pbuf.9 \
|
||||
PCBGROUP.9 \
|
||||
|
93
share/man/man9/owll.9
Normal file
93
share/man/man9/owll.9
Normal file
@ -0,0 +1,93 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2015 M. Warner Losh
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 20, 2015
|
||||
.Dt OWLL 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm owll
|
||||
.Nm OWLL_WRITE_ONE,
|
||||
.Nm OWLL_WRITE_ZERO,
|
||||
.Nm OWLL_READ_DATA,
|
||||
.Nm OWLL_REASET_AND_PRESENCE
|
||||
.Nd Dallas Semiconductor 1-Wire Link Layer Interface
|
||||
.Sh SYNOPSIS
|
||||
.Ft int
|
||||
.Fn OWLL_WRITE_ONE "device_t lldev" "struct ow_timing *timing"
|
||||
.Ft int
|
||||
.Fn OWLL_WRITE_ZERO "device_t lldev" "struct ow_timing *timing"
|
||||
.Ft int
|
||||
.Fn OWLL_READ_DATA "device_t lldev" "struct ow_timing *timing" "int *bit"
|
||||
.Ft int
|
||||
.Fn OWLL_RESET_AND_PRESENCE "device_t lldev" "struct ow_timing *timing" "int *bit"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
interface provides access to the link layer of the Dallas
|
||||
Semiconductor 1-Wire from upper layers of the protocol.
|
||||
.Pp
|
||||
.Fn OWLL_WRITE_ONE
|
||||
and
|
||||
.Fn OWLL_WRITE_ZERO
|
||||
writes a one bitor a zero bit respectively on the 1-Wire bus.
|
||||
.Pp
|
||||
.Fn OWLL_READ_DATA
|
||||
reads one bit from the 1-Wire bus.
|
||||
This is often referred to as a
|
||||
.Dq Read Time Slot
|
||||
in the 1-Wire device data sheets.
|
||||
.Pp
|
||||
The
|
||||
.Fn OWLL_RESET_AND_PRESENCE
|
||||
function starts a reset sequence and detects if any device(s) are
|
||||
present on the bus.
|
||||
This is the beginning of all 1-Wire transactions.
|
||||
.Sh NOTES
|
||||
This interface is intended to be used only by the
|
||||
.Xr ow 4
|
||||
device to talk to the low-level bus.
|
||||
By convention, the device that implements this interface is called
|
||||
.Xr owc 4 .
|
||||
Only devices that implement
|
||||
.Xr own 9
|
||||
should call these interfaces.
|
||||
.Sh SEE ALSO
|
||||
.Xr ow 4 ,
|
||||
.Xr owc 4 ,
|
||||
.Xr own 9
|
||||
.Sh LEGAL
|
||||
.Tn 1-Wire
|
||||
is a registered trademark of Maxim Integrated Products, Inc.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver first appeared in
|
||||
.Fx 11.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were written by
|
||||
.An Warner Losh .
|
230
share/man/man9/own.9
Normal file
230
share/man/man9/own.9
Normal file
@ -0,0 +1,230 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2015 M. Warner Losh
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 20, 2015
|
||||
.Dt OWN 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm own ,
|
||||
.Nm own_send_command ,
|
||||
.Nm own_commmand_wait ,
|
||||
.Nm own_self_command ,
|
||||
.Nm own_acquire_bus ,
|
||||
.Nm own crc ,
|
||||
.Nm own_release_bus ,
|
||||
.Nm OWN_ACQUIRE_BUS ,
|
||||
.Nm OWN_CRC ,
|
||||
.Nm OWN_RELEASE_BUS ,
|
||||
.Nm OWN_SEND_COMMAND
|
||||
.Nd Dallas Semiconductor 1-Wire Network and Transport Interface
|
||||
.Sh SYNOPSIS
|
||||
.In sys/bus.h
|
||||
.In dev/ow/own.h
|
||||
.Ft int
|
||||
.Fn own_send_command "device_t pdev" "struct ow_cmd *cmd"
|
||||
.Ft int
|
||||
.Fn own_command_wait "device_t pdev" "struct ow_cmd *cmd"
|
||||
.Ft int
|
||||
.Fn own_self_command "device_t pdev" "struct ow_cmd *cmd" "uint8_t xpt_cmd"
|
||||
.Ft int
|
||||
.Fn own_acquire_bus "device_t pdev" "int how"
|
||||
.Ft int
|
||||
.Fn own_release_bus "device_t pdev"
|
||||
.Ft int
|
||||
.Fn own_crc "device_t pdev" "uint8_t *buffer" "size_t len"
|
||||
.Ft int
|
||||
.Fn OWN_SEND_COMMAND "device_t ndev" "device_t pdev" "struct ow_cmd *cmd"
|
||||
.Ft int
|
||||
.Fn OWN_ACQUIRE_BUS "device_t ndev" "device_t pdev" "int how"
|
||||
.Ft void
|
||||
.Fn OWN_RELEASE_BUS "device_t ndev" "device_t pdev"
|
||||
.Ft uint8_t
|
||||
.Fn OWN_CRC "device_t ndev" "device_t pdev" "uint8_t *buffer" "size_t len"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
interface defines three sets of functions for interacting with 1-Wire
|
||||
devices:
|
||||
sending commands,
|
||||
reserving the bus,
|
||||
and
|
||||
ensuring data integrity.
|
||||
Wrappers are provided for the raw
|
||||
.Nm OWN
|
||||
.Xr kobj 9
|
||||
interfaces and should be used for improved safety over the
|
||||
.Xr kobj 9
|
||||
ones.
|
||||
.Ss Bus Commands
|
||||
The 1-Wire bus defines different layers of access to the devices on
|
||||
the bus.
|
||||
The
|
||||
.Nm
|
||||
functions provide access to the network and transport layers.
|
||||
The network layer designates the next command as being either for all
|
||||
devices on the bus, or for a specific device.
|
||||
The network layer also specifies the speed used by the link layer.
|
||||
.Pp
|
||||
.Vt "struct ow_cmd"
|
||||
encapsulates network access, speed, and timing information.
|
||||
It specifies the commands to send and whether or not to read data.
|
||||
Its members are:
|
||||
.Bl -tag -width ".Va xxxx"
|
||||
.It Va flags
|
||||
Flags controlling the interpretation of the structure.
|
||||
These flags are defined in
|
||||
.In dev/ow/ow.h :
|
||||
.Bl -tag -width indent
|
||||
.It OW_FLAG_OVERDRIVE
|
||||
Send
|
||||
.Va xpt_cmd
|
||||
bytes and read
|
||||
.Va xpt_read
|
||||
bytes at overdrive speed.
|
||||
.It OW_FLAG_READ_BIT
|
||||
Interpret
|
||||
.Va xpt_read_len
|
||||
to be in bits to be read after
|
||||
.Va xpt_cmd
|
||||
rather than bytes.
|
||||
.El
|
||||
.It Va rom_cmd
|
||||
ROM command bytes to send.
|
||||
.It Va rom_len
|
||||
Number of ROM command bytes to send.
|
||||
.It Va rom_read_len
|
||||
Number of bytes to read after sending the ROM command.
|
||||
.It Va rom_read
|
||||
Buffer for bytes read after the ROM command.
|
||||
.It Va xpt_cmd
|
||||
Transport command to send.
|
||||
.It Va xpt_len
|
||||
Length of the transport command bytes to send.
|
||||
Specify 0 for no transport command.
|
||||
.It Va xpt_read_len
|
||||
Number of bytes to read after
|
||||
.Va xpt_cmd
|
||||
bytes are sent.
|
||||
If the
|
||||
.Dv OW_FLAG_READ_BIT
|
||||
bit is set in
|
||||
.Va flags ,
|
||||
then it is the number of bits to read.
|
||||
Bits read are packed into bytes.
|
||||
.It Va xpt_read
|
||||
Buffer for data read.
|
||||
.El
|
||||
.Pp
|
||||
.Fn own_command_wait
|
||||
acquires the 1-Wire bus, waiting if necessary,
|
||||
sends the command,
|
||||
and
|
||||
then releases the bus.
|
||||
.Fn own_send_command
|
||||
sends the command without bus reservation.
|
||||
.Fa pdev
|
||||
is the client device (the presentation layer device) sending the command.
|
||||
The
|
||||
.Fa cmd
|
||||
argument describes the transaction to send to the 1-Wire bus.
|
||||
.Pp
|
||||
.Fn own_self_command
|
||||
fills in
|
||||
.Fa cmd
|
||||
with a MATCH_ROM ROM command, the ROM address of
|
||||
.Fa pdev
|
||||
and the
|
||||
.Fa xpt_cmd
|
||||
as a convenient way to create directed commands.
|
||||
.Ss Bus Reservation
|
||||
The 1-Wire system includes an advisory lock for the bus that
|
||||
presentation layer devices can use to coordinate access.
|
||||
Locking is purely advisory at this time.
|
||||
.Pp
|
||||
.Fn own_acquire_bus
|
||||
reserves the bus.
|
||||
It waits indefinitely if the
|
||||
.Fa how
|
||||
argument is
|
||||
.Dv OWN_WAIT
|
||||
and returns the error
|
||||
.Dv EWOULDBLOCK
|
||||
if passed
|
||||
.Dv OWN_DONTWAIT
|
||||
when the bus is owned by another client.
|
||||
.Pp
|
||||
.Fn own_release_bus
|
||||
releases the bus.
|
||||
.Ss Data Integrity
|
||||
.Fn own_crc
|
||||
computes the 1-Wire standard CRC function over the data
|
||||
passed in
|
||||
.Fa buffer
|
||||
and
|
||||
.Fa len
|
||||
and returns the result.
|
||||
.Ss Notes
|
||||
The 1-Wire standard (Maxim AN937) defines layers that are akin to ISO
|
||||
networking layers.
|
||||
The lowest relevant layer, the link layer, defines the polling windows
|
||||
and the timing of the signaling of different modes.
|
||||
The network layer is built on top of the link layer
|
||||
and is used to address devices in a unicast or multicast manner.
|
||||
The transport layer defines commands and responses from the devices.
|
||||
The presentation layer is composed of the device specific commands and
|
||||
actions used to control the specific 1-Wire devices on bus.
|
||||
.Pp
|
||||
These interfaces are implemented by the
|
||||
.Xr ow 4
|
||||
device.
|
||||
Presentation layer devices (children of the newbus
|
||||
.Xr ow 4
|
||||
device) should only call the functions described here.
|
||||
The functionality provided by the
|
||||
.Xr owc 4
|
||||
device (specifically the
|
||||
.Xr owll 9
|
||||
interface) should only be called by the
|
||||
.Xr ow 4
|
||||
driver.
|
||||
.Sh SEE ALSO
|
||||
.Xr ow 4 ,
|
||||
.Xr owc 4 ,
|
||||
.Xr owll 9
|
||||
.Pa http://pdfserv.maximintegrated.com/en/an/AN937.pdf
|
||||
.Sh LEGAL
|
||||
.Tn 1-Wire
|
||||
is a registered trademark of Maxim Integrated Products, Inc.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver first appeared in
|
||||
.Fx 11.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were written by
|
||||
.An Warner Losh .
|
@ -2088,6 +2088,13 @@ dev/ofw/ofw_iicbus.c optional fdt iicbus
|
||||
dev/ofw/ofwbus.c optional fdt
|
||||
dev/ofw/openfirm.c optional fdt
|
||||
dev/ofw/openfirmio.c optional fdt
|
||||
dev/ow/ow.c optional ow \
|
||||
dependency "owll_if.h" \
|
||||
dependency "own_if.h"
|
||||
dev/ow/owll_if.m optional ow
|
||||
dev/ow/own_if.m optional ow
|
||||
dev/ow/ow_temp.c optional ow_temp
|
||||
dev/ow/owc_gpiobus.c optional owc gpio
|
||||
dev/patm/if_patm.c optional patm pci
|
||||
dev/patm/if_patm_attach.c optional patm pci
|
||||
dev/patm/if_patm_intr.c optional patm pci
|
||||
|
19
sys/dev/ow/README.txt
Normal file
19
sys/dev/ow/README.txt
Normal file
@ -0,0 +1,19 @@
|
||||
Quick Design Document for 1-wire bus
|
||||
|
||||
In new bus terms, 1-wire devices are attached to 1-wire buses (ow)
|
||||
which are attached to a one wire bridge (owc).
|
||||
|
||||
The implementation follows the terminology used in the Maxim AN927
|
||||
Application note which defines the 1-wire bus as implemented for the
|
||||
iButton product. This is considered to be the canonical definition of
|
||||
the 1-wire bus. This means that the 1-wire bridge will implement the
|
||||
owll(9) interface. ow is one wire. ll is for Link Level to mirror the ISO
|
||||
stack terminology used by AN927. The 1-wire bus is implemented in the ow(4)
|
||||
device, which implements the own(9) interface (n for network, the layer
|
||||
described in the AN927). The presentation layer and above is the
|
||||
responsibility of the client device drivers to implement.
|
||||
|
||||
Client drivers may only call the own(9) interface. The ow(4) driver
|
||||
calls the owll(9) interface and implements the own(9).
|
||||
|
||||
$FreeBSD$
|
639
sys/dev/ow/ow.c
Normal file
639
sys/dev/ow/ow.c
Normal file
@ -0,0 +1,639 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 M. Warner Losh <imp@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/libkern.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <dev/ow/ow.h>
|
||||
#include <dev/ow/owll.h>
|
||||
#include <dev/ow/own.h>
|
||||
|
||||
/*
|
||||
* lldev - link level device
|
||||
* ndev - network / transport device (this module)
|
||||
* pdev - presentation device (children of this module)
|
||||
*/
|
||||
|
||||
typedef int ow_enum_fn(device_t, device_t);
|
||||
typedef int ow_found_fn(device_t, romid_t);
|
||||
|
||||
struct ow_softc
|
||||
{
|
||||
device_t dev; /* Newbus driver back pointer */
|
||||
struct mtx mtx; /* bus mutex */
|
||||
device_t owner; /* bus owner, if != NULL */
|
||||
};
|
||||
|
||||
struct ow_devinfo
|
||||
{
|
||||
romid_t romid;
|
||||
};
|
||||
|
||||
static int ow_acquire_bus(device_t ndev, device_t pdev, int how);
|
||||
static void ow_release_bus(device_t ndev, device_t pdev);
|
||||
|
||||
#define OW_LOCK(_sc) mtx_lock(&(_sc)->mtx)
|
||||
#define OW_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
|
||||
#define OW_LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx)
|
||||
#define OW_ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED)
|
||||
#define OW_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED)
|
||||
|
||||
static MALLOC_DEFINE(M_OW, "ow", "House keeping data for 1wire bus");
|
||||
|
||||
static struct ow_timing timing_regular = {
|
||||
.t_slot = 60, /* 60 to 120 */
|
||||
.t_low0 = 60, /* really 60 to 120 */
|
||||
.t_low1 = 1, /* really 1 to 15 */
|
||||
.t_release = 45, /* <= 45us */
|
||||
.t_rec = 1, /* at least 1us */
|
||||
.t_rdv = 15, /* 15us */
|
||||
.t_rstl = 480, /* 480us or more */
|
||||
.t_rsth = 480, /* 480us or more */
|
||||
.t_pdl = 60, /* 60us to 240us */
|
||||
.t_pdh = 60, /* 15us to 60us */
|
||||
.t_lowr = 1, /* 1us */
|
||||
};
|
||||
|
||||
/* NB: Untested */
|
||||
static struct ow_timing timing_overdrive = {
|
||||
.t_slot = 11, /* 6us to 16us */
|
||||
.t_low0 = 6, /* really 6 to 16 */
|
||||
.t_low1 = 1, /* really 1 to 2 */
|
||||
.t_release = 4, /* <= 4us */
|
||||
.t_rec = 1, /* at least 1us */
|
||||
.t_rdv = 2, /* 2us */
|
||||
.t_rstl = 48, /* 48us to 80us */
|
||||
.t_rsth = 48, /* 48us or more */
|
||||
.t_pdl = 8, /* 8us to 24us */
|
||||
.t_pdh = 2, /* 2us to 6us */
|
||||
.t_lowr = 1, /* 1us */
|
||||
};
|
||||
|
||||
static void
|
||||
ow_send_byte(device_t lldev, struct ow_timing *t, uint8_t byte)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
if (byte & (1 << i))
|
||||
OWLL_WRITE_ONE(lldev, t);
|
||||
else
|
||||
OWLL_WRITE_ZERO(lldev, t);
|
||||
}
|
||||
|
||||
static void
|
||||
ow_read_byte(device_t lldev, struct ow_timing *t, uint8_t *bytep)
|
||||
{
|
||||
int i;
|
||||
uint8_t byte = 0;
|
||||
int bit;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
OWLL_READ_DATA(lldev, t, &bit);
|
||||
byte |= bit << i;
|
||||
}
|
||||
*bytep = byte;
|
||||
}
|
||||
|
||||
static int
|
||||
ow_send_command(device_t ndev, device_t pdev, struct ow_cmd *cmd)
|
||||
{
|
||||
int present, i, bit, tries;
|
||||
device_t lldev;
|
||||
struct ow_timing *t;
|
||||
|
||||
lldev = device_get_parent(ndev);
|
||||
|
||||
/*
|
||||
* Retry the reset a couple of times before giving up.
|
||||
*/
|
||||
tries = 4;
|
||||
do {
|
||||
OWLL_RESET_AND_PRESENCE(lldev, &timing_regular, &present);
|
||||
if (present == 1)
|
||||
device_printf(ndev, "Reset said no device on bus?.\n");
|
||||
} while (present == 1 && tries-- > 0);
|
||||
if (present == 1) {
|
||||
device_printf(ndev, "Reset said the device wasn't there.\n");
|
||||
return ENOENT; /* No devices acked the RESET */
|
||||
}
|
||||
if (present == -1) {
|
||||
device_printf(ndev, "Reset discovered bus wired wrong.\n");
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
for (i = 0; i < cmd->rom_len; i++)
|
||||
ow_send_byte(lldev, &timing_regular, cmd->rom_cmd[i]);
|
||||
for (i = 0; i < cmd->rom_read_len; i++)
|
||||
ow_read_byte(lldev, &timing_regular, cmd->rom_read + i);
|
||||
if (cmd->xpt_len) {
|
||||
/*
|
||||
* Per AN937, the reset pulse and ROM level are always
|
||||
* done with the regular timings. Certain ROM commands
|
||||
* put the device into overdrive mode for the remainder
|
||||
* of the data transfer, which is why we have to pass the
|
||||
* timings here. Commands that need to be handled like this
|
||||
* are expected to be flagged by the client.
|
||||
*/
|
||||
t = (cmd->flags & OW_FLAG_OVERDRIVE) ?
|
||||
&timing_overdrive : &timing_regular;
|
||||
for (i = 0; i < cmd->xpt_len; i++)
|
||||
ow_send_byte(lldev, t, cmd->xpt_cmd[i]);
|
||||
if (cmd->flags & OW_FLAG_READ_BIT) {
|
||||
memset(cmd->xpt_read, 0, (cmd->xpt_read_len + 7) / 8);
|
||||
for (i = 0; i < cmd->xpt_read_len; i++) {
|
||||
OWLL_READ_DATA(lldev, t, &bit);
|
||||
cmd->xpt_read[i / 8] |= bit << (i % 8);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < cmd->xpt_read_len; i++)
|
||||
ow_read_byte(lldev, t, cmd->xpt_read + i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ow_search_rom(device_t lldev, device_t dev)
|
||||
{
|
||||
struct ow_cmd cmd;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.rom_cmd[0] = SEARCH_ROM;
|
||||
cmd.rom_len = 1;
|
||||
return ow_send_command(lldev, dev, &cmd);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
ow_alarm_search(device_t lldev, device_t dev)
|
||||
{
|
||||
struct ow_cmd cmd;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.rom_cmd[0] = ALARM_SEARCH;
|
||||
cmd.rom_len = 1;
|
||||
return ow_send_command(lldev, dev, &cmd);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ow_add_child(device_t dev, romid_t romid)
|
||||
{
|
||||
struct ow_devinfo *di;
|
||||
device_t child;
|
||||
|
||||
di = malloc(sizeof(*di), M_OW, M_WAITOK);
|
||||
di->romid = romid;
|
||||
child = device_add_child(dev, NULL, -1);
|
||||
if (child == NULL) {
|
||||
free(di, M_OW);
|
||||
return ENOMEM;
|
||||
}
|
||||
device_set_ivars(child, di);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_t
|
||||
ow_child_by_romid(device_t dev, romid_t romid)
|
||||
{
|
||||
device_t *children, retval, child;
|
||||
int nkid, i;
|
||||
struct ow_devinfo *di;
|
||||
|
||||
if (device_get_children(dev, &children, &nkid) != 0)
|
||||
return (NULL);
|
||||
retval = NULL;
|
||||
for (i = 0; i < nkid; i++) {
|
||||
child = children[i];
|
||||
di = device_get_ivars(child);
|
||||
if (di->romid == romid) {
|
||||
retval = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(children, M_TEMP);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* CRC generator table -- taken from AN937 DOW CRC LOOKUP FUNCTION Table 2
|
||||
*/
|
||||
const uint8_t ow_crc_table[] = {
|
||||
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
|
||||
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
|
||||
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
|
||||
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
|
||||
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
|
||||
219, 133,103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
|
||||
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
|
||||
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
|
||||
140,210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113,147, 205,
|
||||
17, 79, 173, 243, 112, 46, 204, 146, 211,141, 111, 49, 178, 236, 14, 80,
|
||||
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82,176, 238,
|
||||
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
|
||||
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
|
||||
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
|
||||
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
|
||||
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
|
||||
};
|
||||
|
||||
/*
|
||||
* Converted from DO_CRC page 131 ANN937
|
||||
*/
|
||||
static uint8_t
|
||||
ow_crc(device_t ndev, device_t pdev, uint8_t *buffer, size_t len)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
crc = ow_crc_table[crc ^ buffer[i]];
|
||||
return crc;
|
||||
}
|
||||
|
||||
static int
|
||||
ow_check_crc(romid_t romid)
|
||||
{
|
||||
return ow_crc(NULL, NULL, (uint8_t *)&romid, sizeof(romid)) == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ow_device_found(device_t dev, romid_t romid)
|
||||
{
|
||||
|
||||
/* XXX Move this up into enumerate? */
|
||||
/*
|
||||
* All valid ROM IDs have a valid CRC. Check that first.
|
||||
*/
|
||||
if (!ow_check_crc(romid)) {
|
||||
device_printf(dev, "Device romid %8D failed CRC.\n",
|
||||
&romid, ":");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've seen this child before, don't add a new one for it.
|
||||
*/
|
||||
if (ow_child_by_romid(dev, romid) != NULL)
|
||||
return 0;
|
||||
|
||||
return ow_add_child(dev, romid);
|
||||
}
|
||||
|
||||
static int
|
||||
ow_enumerate(device_t dev, ow_enum_fn *enumfp, ow_found_fn *foundfp)
|
||||
{
|
||||
device_t lldev = device_get_parent(dev);
|
||||
int first, second, i, dir, prior, last, err, retries;
|
||||
uint64_t probed, last_mask;
|
||||
int sanity = 10;
|
||||
|
||||
prior = -1;
|
||||
last_mask = 0;
|
||||
retries = 0;
|
||||
last = -2;
|
||||
err = ow_acquire_bus(dev, dev, OWN_DONTWAIT);
|
||||
if (err != 0)
|
||||
return err;
|
||||
while (last != -1) {
|
||||
if (sanity-- < 0) {
|
||||
printf("Reached the sanity limit\n");
|
||||
return EIO;
|
||||
}
|
||||
again:
|
||||
probed = 0;
|
||||
last = -1;
|
||||
|
||||
/*
|
||||
* See AN397 section 5.II.C.3 for the algorithm (though a bit
|
||||
* poorly stated). The search command forces each device to
|
||||
* send ROM ID bits one at a time (first the bit, then the
|
||||
* complement) the the master (us) sends back a bit. If the
|
||||
* device's bit doesn't match what we send back, that device
|
||||
* stops sending bits back. So each time through we remember
|
||||
* where we made the last decision (always 0). If there's a
|
||||
* conflict there this time (and there will be in the absence
|
||||
* of a hardware failure) we go with 1. This way, we prune the
|
||||
* devices on the bus and wind up with a unique ROM. We know
|
||||
* we're done when we detect no new conflicts. The same
|
||||
* algorithm is used for devices in alarm state as well.
|
||||
*
|
||||
* In addition, experience has shown that sometimes devices
|
||||
* stop responding in the middle of enumeration, so try this
|
||||
* step again a few times when that happens. It is unclear if
|
||||
* this is due to a nosiy electrical environment or some odd
|
||||
* timing issue.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The enumeration command should be successfully sent, if not,
|
||||
* we have big issues on the bus so punt. Lower layers report
|
||||
* any unusual errors, so we don't need to here.
|
||||
*/
|
||||
err = enumfp(dev, dev);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
OWLL_READ_DATA(lldev, &timing_regular, &first);
|
||||
OWLL_READ_DATA(lldev, &timing_regular, &second);
|
||||
switch (first | second << 1) {
|
||||
case 0: /* Conflict */
|
||||
if (i < prior)
|
||||
dir = (last_mask >> i) & 1;
|
||||
else
|
||||
dir = i == prior;
|
||||
|
||||
if (dir == 0)
|
||||
last = i;
|
||||
break;
|
||||
case 1: /* 1 then 0 -> 1 for all */
|
||||
dir = 1;
|
||||
break;
|
||||
case 2: /* 0 then 1 -> 0 for all */
|
||||
dir = 0;
|
||||
break;
|
||||
case 3:
|
||||
/*
|
||||
* No device responded. This is unexpected, but
|
||||
* experience has shown that on some platforms
|
||||
* we miss a timing window, or otherwise have
|
||||
* an issue. Start this step over. Since we've
|
||||
* not updated prior yet, we can just jump to
|
||||
* the top of the loop for a re-do of this step.
|
||||
*/
|
||||
printf("oops, starting over\n");
|
||||
if (++retries > 5)
|
||||
return (EIO);
|
||||
goto again;
|
||||
}
|
||||
if (dir) {
|
||||
OWLL_WRITE_ONE(lldev, &timing_regular);
|
||||
probed |= 1ull << i;
|
||||
} else {
|
||||
OWLL_WRITE_ZERO(lldev, &timing_regular);
|
||||
}
|
||||
}
|
||||
retries = 0;
|
||||
foundfp(dev, probed);
|
||||
last_mask = probed;
|
||||
prior = last;
|
||||
};
|
||||
ow_release_bus(dev, dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ow_probe(device_t dev)
|
||||
{
|
||||
|
||||
device_set_desc(dev, "1 Wire Bus");
|
||||
return (BUS_PROBE_GENERIC);
|
||||
}
|
||||
|
||||
static int
|
||||
ow_attach(device_t ndev)
|
||||
{
|
||||
struct ow_softc *sc;
|
||||
|
||||
/*
|
||||
* Find all the devices on the bus. We don't probe / attach them in the
|
||||
* enumeration phase. We do this because we want to allow the probe /
|
||||
* attach routines of the child drivers to have as full an access to the
|
||||
* bus as possible. While we reset things before the next step of the
|
||||
* search (so it would likely be OK to allow access by the clients to
|
||||
* the bus), it is more conservative to find them all, then to do the
|
||||
* attach of the devices. This also allows the child devices to have
|
||||
* more knowledge of the bus. We also ignore errors from the enumeration
|
||||
* because they might happen after we've found a few devices.
|
||||
*/
|
||||
sc = device_get_softc(ndev);
|
||||
sc->dev = ndev;
|
||||
mtx_init(&sc->mtx, device_get_nameunit(sc->dev), "ow", MTX_DEF);
|
||||
ow_enumerate(ndev, ow_search_rom, ow_device_found);
|
||||
return bus_generic_attach(ndev);
|
||||
}
|
||||
|
||||
static int
|
||||
ow_detach(device_t ndev)
|
||||
{
|
||||
device_t *children, child;
|
||||
int nkid, i;
|
||||
struct ow_devinfo *di;
|
||||
struct ow_softc *sc;
|
||||
|
||||
sc = device_get_softc(ndev);
|
||||
/*
|
||||
* detach all the children first. This is blocking until any threads
|
||||
* have stopped, etc.
|
||||
*/
|
||||
bus_generic_detach(ndev);
|
||||
|
||||
/*
|
||||
* We delete all the children, and free up the ivars
|
||||
*/
|
||||
if (device_get_children(ndev, &children, &nkid) != 0)
|
||||
return ENOMEM;
|
||||
for (i = 0; i < nkid; i++) {
|
||||
child = children[i];
|
||||
di = device_get_ivars(child);
|
||||
free(di, M_OW);
|
||||
device_delete_child(ndev, child);
|
||||
}
|
||||
free(children, M_TEMP);
|
||||
|
||||
OW_LOCK_DESTROY(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Not sure this is really needed. I'm having trouble figuring out what
|
||||
* location means in the context of the one wire bus.
|
||||
*/
|
||||
static int
|
||||
ow_child_location_str(device_t dev, device_t child, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
|
||||
snprintf(buf, buflen, "");
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ow_child_pnpinfo_str(device_t dev, device_t child, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
struct ow_devinfo *di;
|
||||
|
||||
di = device_get_ivars(child);
|
||||
snprintf(buf, buflen, "romid=%8D", &di->romid, ":");
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ow_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
||||
{
|
||||
struct ow_devinfo *di;
|
||||
romid_t **ptr;
|
||||
|
||||
di = device_get_ivars(child);
|
||||
switch (which) {
|
||||
case OW_IVAR_FAMILY:
|
||||
*result = di->romid & 0xff;
|
||||
break;
|
||||
case OW_IVAR_ROMID:
|
||||
ptr = (romid_t **)result;
|
||||
*ptr = &di->romid;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ow_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
|
||||
{
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
ow_print_child(device_t ndev, device_t pdev)
|
||||
{
|
||||
int retval = 0;
|
||||
struct ow_devinfo *di;
|
||||
|
||||
di = device_get_ivars(pdev);
|
||||
|
||||
retval += bus_print_child_header(ndev, pdev);
|
||||
retval += printf(" romid %8D", &di->romid, ":");
|
||||
retval += bus_print_child_footer(ndev, pdev);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
ow_probe_nomatch(device_t ndev, device_t pdev)
|
||||
{
|
||||
struct ow_devinfo *di;
|
||||
|
||||
di = device_get_ivars(pdev);
|
||||
device_printf(ndev, "romid %8D: no driver\n", &di->romid, ":");
|
||||
}
|
||||
|
||||
static int
|
||||
ow_acquire_bus(device_t ndev, device_t pdev, int how)
|
||||
{
|
||||
struct ow_softc *sc;
|
||||
|
||||
sc = device_get_softc(ndev);
|
||||
OW_ASSERT_UNLOCKED(sc);
|
||||
OW_LOCK(sc);
|
||||
if (sc->owner != NULL) {
|
||||
if (sc->owner == pdev)
|
||||
panic("%s: %s recursively acquiring the bus.\n",
|
||||
device_get_nameunit(ndev),
|
||||
device_get_nameunit(pdev));
|
||||
if (how == OWN_DONTWAIT) {
|
||||
OW_UNLOCK(sc);
|
||||
return EWOULDBLOCK;
|
||||
}
|
||||
while (sc->owner != NULL)
|
||||
mtx_sleep(sc, &sc->mtx, 0, "owbuswait", 0);
|
||||
}
|
||||
sc->owner = pdev;
|
||||
OW_UNLOCK(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ow_release_bus(device_t ndev, device_t pdev)
|
||||
{
|
||||
struct ow_softc *sc;
|
||||
|
||||
sc = device_get_softc(ndev);
|
||||
OW_ASSERT_UNLOCKED(sc);
|
||||
OW_LOCK(sc);
|
||||
if (sc->owner == NULL)
|
||||
panic("%s: %s releasing unowned bus.", device_get_nameunit(ndev),
|
||||
device_get_nameunit(pdev));
|
||||
if (sc->owner != pdev)
|
||||
panic("%s: %s don't own the bus. %s does. game over.",
|
||||
device_get_nameunit(ndev), device_get_nameunit(pdev),
|
||||
device_get_nameunit(sc->owner));
|
||||
sc->owner = NULL;
|
||||
wakeup(sc);
|
||||
OW_UNLOCK(sc);
|
||||
}
|
||||
|
||||
devclass_t ow_devclass;
|
||||
|
||||
static device_method_t ow_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, ow_probe),
|
||||
DEVMETHOD(device_attach, ow_attach),
|
||||
DEVMETHOD(device_detach, ow_detach),
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_child_pnpinfo_str, ow_child_pnpinfo_str),
|
||||
DEVMETHOD(bus_child_location_str, ow_child_location_str),
|
||||
DEVMETHOD(bus_read_ivar, ow_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, ow_write_ivar),
|
||||
DEVMETHOD(bus_print_child, ow_print_child),
|
||||
DEVMETHOD(bus_probe_nomatch, ow_probe_nomatch),
|
||||
|
||||
/* One Wire Network/Transport layer interface */
|
||||
DEVMETHOD(own_send_command, ow_send_command),
|
||||
DEVMETHOD(own_acquire_bus, ow_acquire_bus),
|
||||
DEVMETHOD(own_release_bus, ow_release_bus),
|
||||
DEVMETHOD(own_crc, ow_crc),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t ow_driver = {
|
||||
"ow",
|
||||
ow_methods,
|
||||
sizeof(struct ow_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(ow, owc, ow_driver, ow_devclass, 0, 0);
|
||||
MODULE_VERSION(ow, 1);
|
77
sys/dev/ow/ow.h
Normal file
77
sys/dev/ow/ow.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 M. Warner Losh <imp@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef DEV_OW_OW_H
|
||||
#define DEV_OW_OW_H 1
|
||||
|
||||
enum ow_device_ivars {
|
||||
OW_IVAR_FAMILY,
|
||||
OW_IVAR_ROMID
|
||||
};
|
||||
|
||||
#define OW_ACCESSOR(var, ivar, type) \
|
||||
__BUS_ACCESSOR(ow, var, OW, ivar, type);
|
||||
|
||||
OW_ACCESSOR(family, FAMILY, uint8_t)
|
||||
OW_ACCESSOR(romid, ROMID, uint8_t *)
|
||||
|
||||
#undef OW_ACCSSOR
|
||||
|
||||
/*
|
||||
* The following likely should be in the own.h file, but needs to be here to
|
||||
* avoid recursive issues when defining the own_if.m interface.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generalized command structure for a 1wire bus transaction. Not all possible
|
||||
* transactions on the 1wire bus can be represented here (a notable exception
|
||||
* being both the search ROM commands), but most of them can be, allowing for
|
||||
* general transactions from userland. A lower-level interface to the link
|
||||
* layer is also provided.
|
||||
*/
|
||||
#define MAX_ROM 10
|
||||
#define MAX_XPT 32
|
||||
#define MAX_READ 32
|
||||
struct ow_cmd
|
||||
{
|
||||
uint32_t flags; /* Various flags */
|
||||
#define OW_FLAG_OVERDRIVE 1 /* Send xpt stuff overdrive speed */
|
||||
#define OW_FLAG_READ_BIT 2 /* Read a single bit after xpt_cmd */
|
||||
uint8_t rom_len; /* Number of ROM bytes to send */
|
||||
uint8_t rom_cmd[MAX_ROM]; /* Rom command to send */
|
||||
uint8_t rom_read_len; /* Number of bytes to read */
|
||||
uint8_t rom_read[MAX_ROM]; /* Extra bytes read */
|
||||
uint8_t xpt_len; /* Total transport bytes to send */
|
||||
uint8_t xpt_cmd[MAX_XPT]; /* Device specific command to send, if flagged */
|
||||
uint8_t xpt_read_len; /* Number of bytes to read after */
|
||||
uint8_t xpt_read[MAX_READ]; /* Buffer for read bytes */
|
||||
};
|
||||
|
||||
typedef uint64_t romid_t;
|
||||
|
||||
#endif /* DEV_OW_OW_H */
|
285
sys/dev/ow/ow_temp.c
Normal file
285
sys/dev/ow/ow_temp.c
Normal file
@ -0,0 +1,285 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 M. Warner Losh <imp@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/libkern.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <dev/ow/ow.h>
|
||||
#include <dev/ow/own.h>
|
||||
|
||||
#define OWT_DS1820 0x10 /* Also 18S20 */
|
||||
#define OWT_DS1822 0x22 /* Very close to 18B20 */
|
||||
#define OWT_DS18B20 0x28 /* Also MAX31820 */
|
||||
#define OWT_DS1825 0x3B /* Just like 18B20 with address bits */
|
||||
|
||||
#define CONVERT_T 0x44
|
||||
#define COPY_SCRATCHPAD 0x48
|
||||
#define WRITE_SCRATCHPAD 0x4e
|
||||
#define READ_POWER_SUPPLY 0xb4
|
||||
#define RECALL_EE 0xb8
|
||||
#define READ_SCRATCHPAD 0xbe
|
||||
|
||||
|
||||
#define OW_TEMP_DONE 0x01
|
||||
#define OW_TEMP_RUNNING 0x02
|
||||
|
||||
struct ow_temp_softc
|
||||
{
|
||||
device_t dev;
|
||||
int type;
|
||||
int temp;
|
||||
int flags;
|
||||
int bad_crc;
|
||||
int bad_reads;
|
||||
int reading_interval;
|
||||
int parasite;
|
||||
struct mtx temp_lock;
|
||||
struct proc *event_thread;
|
||||
};
|
||||
|
||||
static int
|
||||
ow_temp_probe(device_t dev)
|
||||
{
|
||||
|
||||
switch (ow_get_family(dev)) {
|
||||
case OWT_DS1820:
|
||||
device_set_desc(dev, "One Wire Temperature");
|
||||
return BUS_PROBE_DEFAULT;
|
||||
case OWT_DS1822:
|
||||
case OWT_DS1825:
|
||||
case OWT_DS18B20:
|
||||
device_set_desc(dev, "Advanced One Wire Temperature");
|
||||
return BUS_PROBE_DEFAULT;
|
||||
default:
|
||||
return ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ow_temp_read_scratchpad(device_t dev, uint8_t *scratch, int len)
|
||||
{
|
||||
struct ow_cmd cmd;
|
||||
|
||||
own_self_command(dev, &cmd, READ_SCRATCHPAD);
|
||||
cmd.xpt_read_len = len;
|
||||
own_command_wait(dev, &cmd);
|
||||
memcpy(scratch, cmd.xpt_read, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ow_temp_convert_t(device_t dev)
|
||||
{
|
||||
struct ow_cmd cmd;
|
||||
|
||||
own_self_command(dev, &cmd, CONVERT_T);
|
||||
own_command_wait(dev, &cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ow_temp_read_power_supply(device_t dev, int *parasite)
|
||||
{
|
||||
struct ow_cmd cmd;
|
||||
|
||||
own_self_command(dev, &cmd, READ_POWER_SUPPLY);
|
||||
cmd.flags |= OW_FLAG_READ_BIT;
|
||||
cmd.xpt_read_len = 1;
|
||||
own_command_wait(dev, &cmd);
|
||||
*parasite = !cmd.xpt_read[0]; /* parasites pull bus low */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ow_temp_event_thread(void *arg)
|
||||
{
|
||||
struct ow_temp_softc *sc;
|
||||
uint8_t scratch[8 + 1];
|
||||
uint8_t crc;
|
||||
int retries, rv;
|
||||
|
||||
sc = arg;
|
||||
pause("owtstart", device_get_unit(sc->dev) * hz / 100); // 10ms stagger
|
||||
mtx_lock(&sc->temp_lock);
|
||||
sc->flags |= OW_TEMP_RUNNING;
|
||||
ow_temp_read_power_supply(sc->dev, &sc->parasite);
|
||||
if (sc->parasite)
|
||||
device_printf(sc->dev, "Running in parasitic mode unsupported\n");
|
||||
while ((sc->flags & OW_TEMP_DONE) == 0) {
|
||||
mtx_unlock(&sc->temp_lock);
|
||||
ow_temp_convert_t(sc->dev);
|
||||
mtx_lock(&sc->temp_lock);
|
||||
msleep(sc, &sc->temp_lock, 0, "owtcvt", hz);
|
||||
if (sc->flags & OW_TEMP_DONE)
|
||||
break;
|
||||
for (retries = 5; retries > 0; retries--) {
|
||||
mtx_unlock(&sc->temp_lock);
|
||||
rv = ow_temp_read_scratchpad(sc->dev, scratch, sizeof(scratch));
|
||||
mtx_lock(&sc->temp_lock);
|
||||
if (rv == 0) {
|
||||
crc = own_crc(sc->dev, scratch, sizeof(scratch) - 1);
|
||||
if (crc == scratch[8]) {
|
||||
if (sc->type == OWT_DS1820) {
|
||||
if (scratch[7]) {
|
||||
/*
|
||||
* Formula from DS18S20 datasheet, page 6
|
||||
* DS18S20 datahseet says count_per_c is 16, DS1820 does not
|
||||
*/
|
||||
sc->temp = (int16_t)((scratch[0] & 0xfe) |
|
||||
(scratch[1] << 8)) << 3;
|
||||
sc->temp += 16 - scratch[6] - 4; /* count_per_c == 16 */
|
||||
} else
|
||||
sc->temp = (int16_t)(scratch[0] | (scratch[1] << 8)) << 3;
|
||||
} else
|
||||
sc->temp = (int16_t)(scratch[0] | (scratch[1] << 8));
|
||||
sc->temp = sc->temp * 1000 / 16 + 273150;
|
||||
break;
|
||||
}
|
||||
sc->bad_crc++;
|
||||
} else
|
||||
sc->bad_reads++;
|
||||
}
|
||||
msleep(sc, &sc->temp_lock, 0, "owtcvt", sc->reading_interval);
|
||||
}
|
||||
sc->flags &= ~OW_TEMP_RUNNING;
|
||||
mtx_unlock(&sc->temp_lock);
|
||||
kproc_exit(0);
|
||||
}
|
||||
|
||||
static int
|
||||
ow_temp_attach(device_t dev)
|
||||
{
|
||||
struct ow_temp_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
sc->type = ow_get_family(dev);
|
||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
|
||||
OID_AUTO, "temperature", CTLFLAG_RD | CTLTYPE_INT,
|
||||
&sc->temp, 0, sysctl_handle_int,
|
||||
"IK3", "Current Temperature");
|
||||
SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
|
||||
OID_AUTO, "badcrc", CTLFLAG_RD,
|
||||
&sc->bad_crc, 0,
|
||||
"Number of Bad CRC on reading scratchpad");
|
||||
SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
|
||||
OID_AUTO, "badread", CTLFLAG_RD,
|
||||
&sc->bad_reads, 0,
|
||||
"Number of errors on reading scratchpad");
|
||||
SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
|
||||
OID_AUTO, "reading_interval", CTLFLAG_RW,
|
||||
&sc->reading_interval, 0,
|
||||
"ticks between reads");
|
||||
SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
|
||||
OID_AUTO, "parasite", CTLFLAG_RW,
|
||||
&sc->parasite, 0,
|
||||
"In Parasite mode");
|
||||
/*
|
||||
* Just do this for unit 0 to avoid locking
|
||||
* the ow bus until that code can be put
|
||||
* into place.
|
||||
*/
|
||||
sc->temp = -1;
|
||||
sc->reading_interval = 10 * hz;
|
||||
mtx_init(&sc->temp_lock, "lock for doing temperature", NULL, MTX_DEF);
|
||||
/* Start the thread */
|
||||
if (kproc_create(ow_temp_event_thread, sc, &sc->event_thread, 0, 0,
|
||||
"%s event thread", device_get_nameunit(dev))) {
|
||||
device_printf(dev, "unable to create event thread.\n");
|
||||
panic("cbb_create_event_thread");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ow_temp_detach(device_t dev)
|
||||
{
|
||||
struct ow_temp_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/*
|
||||
* Wait for the thread to die. kproc_exit will do a wakeup
|
||||
* on the event thread's struct thread * so that we know it is
|
||||
* safe to proceed. IF the thread is running, set the please
|
||||
* die flag and wait for it to comply. Since the wakeup on
|
||||
* the event thread happens only in kproc_exit, we don't
|
||||
* need to loop here.
|
||||
*/
|
||||
mtx_lock(&sc->temp_lock);
|
||||
sc->flags |= OW_TEMP_DONE;
|
||||
while (sc->flags & OW_TEMP_RUNNING) {
|
||||
wakeup(sc);
|
||||
msleep(sc->event_thread, &sc->temp_lock, PWAIT, "owtun", 0);
|
||||
}
|
||||
mtx_destroy(&sc->temp_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
devclass_t ow_temp_devclass;
|
||||
|
||||
static device_method_t ow_temp_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, ow_temp_probe),
|
||||
DEVMETHOD(device_attach, ow_temp_attach),
|
||||
DEVMETHOD(device_detach, ow_temp_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t ow_temp_driver = {
|
||||
"ow_temp",
|
||||
ow_temp_methods,
|
||||
sizeof(struct ow_temp_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(ow_temp, ow, ow_temp_driver, ow_temp_devclass, 0, 0);
|
||||
MODULE_DEPEND(ow_temp, ow, 1, 1, 1);
|
420
sys/dev/ow/owc_gpiobus.c
Normal file
420
sys/dev/ow/owc_gpiobus.c
Normal file
@ -0,0 +1,420 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 M. Warner Losh <imp@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_platform.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/gpio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#ifdef FDT
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
#endif
|
||||
|
||||
#include <dev/gpio/gpiobusvar.h>
|
||||
#include "gpiobus_if.h"
|
||||
|
||||
#include <dev/ow/owll.h>
|
||||
|
||||
#define OW_PIN 0
|
||||
|
||||
#define OWC_GPIOBUS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
|
||||
#define OWC_GPIOBUS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
|
||||
#define OWC_GPIOBUS_LOCK_INIT(_sc) \
|
||||
mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
|
||||
"owc_gpiobus", MTX_DEF)
|
||||
#define OWC_GPIOBUS_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
|
||||
|
||||
struct owc_gpiobus_softc
|
||||
{
|
||||
device_t sc_dev;
|
||||
device_t sc_busdev;
|
||||
struct mtx sc_mtx;
|
||||
};
|
||||
|
||||
static int owc_gpiobus_probe(device_t);
|
||||
static int owc_gpiobus_attach(device_t);
|
||||
static int owc_gpiobus_detach(device_t);
|
||||
|
||||
#ifdef FDT
|
||||
static void
|
||||
owc_gpiobus_identify(driver_t *driver, device_t bus)
|
||||
{
|
||||
phandle_t w1, root;
|
||||
|
||||
/*
|
||||
* Find all the 1-wire bus pseudo-nodes that are
|
||||
* at the top level of the FDT. Would be nice to
|
||||
* somehow preserve the node name of these busses,
|
||||
* but there's no good place to put it. The driver's
|
||||
* name is used for the device name, and the 1-wire
|
||||
* bus overwrites the description.
|
||||
*/
|
||||
root = OF_finddevice("/");
|
||||
if (root == 0)
|
||||
return;
|
||||
for (w1 = OF_child(root); w1 != 0; w1 = OF_peer(w1)) {
|
||||
if (!fdt_is_compatible_strict(w1, "w1-gpio"))
|
||||
continue;
|
||||
if (!OF_hasprop(w1, "gpios"))
|
||||
continue;
|
||||
ofw_gpiobus_add_fdt_child(bus, driver->name, w1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
owc_gpiobus_probe(device_t dev)
|
||||
{
|
||||
#ifdef FDT
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (ofw_bus_is_compatible(dev, "w1-gpio")) {
|
||||
device_set_desc(dev, "FDT GPIO attached one-wire bus");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
#else
|
||||
device_set_desc(dev, "GPIO attached one-wire bus");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
owc_gpiobus_attach(device_t dev)
|
||||
{
|
||||
struct owc_gpiobus_softc *sc;
|
||||
device_t *kids;
|
||||
int nkid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->sc_dev = dev;
|
||||
sc->sc_busdev = device_get_parent(dev);
|
||||
OWC_GPIOBUS_LOCK_INIT(sc);
|
||||
nkid = 0;
|
||||
if (device_get_children(dev, &kids, &nkid) == 0)
|
||||
free(kids, M_TEMP);
|
||||
if (nkid == 0)
|
||||
device_add_child(dev, "ow", -1);
|
||||
bus_generic_attach(dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
owc_gpiobus_detach(device_t dev)
|
||||
{
|
||||
struct owc_gpiobus_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
OWC_GPIOBUS_LOCK_DESTROY(sc);
|
||||
bus_generic_detach(dev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* In the diagrams below, R is driven by the resistor pullup, M is driven by the
|
||||
* master, and S is driven by the slave / target.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These macros let what why we're doing stuff shine in the code
|
||||
* below, and let the how be confined to here.
|
||||
*/
|
||||
#define GETBUS(sc) GPIOBUS_ACQUIRE_BUS((sc)->sc_busdev, \
|
||||
(sc)->sc_dev, GPIOBUS_WAIT)
|
||||
#define RELBUS(sc) GPIOBUS_RELEASE_BUS((sc)->sc_busdev, \
|
||||
(sc)->sc_dev)
|
||||
#define OUTPIN(sc) GPIOBUS_PIN_SETFLAGS((sc)->sc_busdev, \
|
||||
(sc)->sc_dev, OW_PIN, GPIO_PIN_OUTPUT)
|
||||
#define INPIN(sc) GPIOBUS_PIN_SETFLAGS((sc)->sc_busdev, \
|
||||
(sc)->sc_dev, OW_PIN, GPIO_PIN_INPUT)
|
||||
#define GETPIN(sc, bit) GPIOBUS_PIN_GET((sc)->sc_busdev, \
|
||||
(sc)->sc_dev, OW_PIN, bit)
|
||||
#define LOW(sc) GPIOBUS_PIN_SET((sc)->sc_busdev, \
|
||||
(sc)->sc_dev, OW_PIN, GPIO_PIN_LOW)
|
||||
|
||||
/*
|
||||
* WRITE-ONE (see owll_if.m for timings) From Figure 4-1 AN-937
|
||||
*
|
||||
* |<---------tSLOT---->|<-tREC->|
|
||||
* High RRRRM | RRRRRRRRRRRR|RRRRRRRRM
|
||||
* M | R | | | M
|
||||
* M| R | | | M
|
||||
* Low MMMMMMM | | | MMMMMM...
|
||||
* |<-tLOW1->| | |
|
||||
* |<------15us--->| |
|
||||
* |<--------60us---->|
|
||||
*/
|
||||
static int
|
||||
owc_gpiobus_write_one(device_t dev, struct ow_timing *t)
|
||||
{
|
||||
struct owc_gpiobus_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
error = GETBUS(sc);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
critical_enter();
|
||||
|
||||
/* Force low */
|
||||
OUTPIN(sc);
|
||||
LOW(sc);
|
||||
DELAY(t->t_low1);
|
||||
|
||||
/* Allow resistor to float line high */
|
||||
INPIN(sc);
|
||||
DELAY(t->t_slot - t->t_low1 + t->t_rec);
|
||||
|
||||
critical_exit();
|
||||
|
||||
RELBUS(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* WRITE-ZERO (see owll_if.m for timings) From Figure 4-2 AN-937
|
||||
*
|
||||
* |<---------tSLOT------>|<-tREC->|
|
||||
* High RRRRM | | |RRRRRRRM
|
||||
* M | | R M
|
||||
* M| | | |R M
|
||||
* Low MMMMMMMMMMMMMMMMMMMMMR MMMMMM...
|
||||
* |<--15us->| | |
|
||||
* |<------60us--->| |
|
||||
* |<-------tLOW0------>|
|
||||
*/
|
||||
static int
|
||||
owc_gpiobus_write_zero(device_t dev, struct ow_timing *t)
|
||||
{
|
||||
struct owc_gpiobus_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
error = GETBUS(sc);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
critical_enter();
|
||||
|
||||
/* Force low */
|
||||
OUTPIN(sc);
|
||||
LOW(sc);
|
||||
DELAY(t->t_low0);
|
||||
|
||||
/* Allow resistor to float line high */
|
||||
INPIN(sc);
|
||||
DELAY(t->t_slot - t->t_low0 + t->t_rec);
|
||||
|
||||
critical_exit();
|
||||
|
||||
RELBUS(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* READ-DATA (see owll_if.m for timings) From Figure 4-3 AN-937
|
||||
*
|
||||
* |<---------tSLOT------>|<-tREC->|
|
||||
* High RRRRM | rrrrrrrrrrrrrrrRRRRRRRM
|
||||
* M | r | R M
|
||||
* M| r | |R M
|
||||
* Low MMMMMMMSSSSSSSSSSSSSSR MMMMMM...
|
||||
* |<tLOWR>< sample > |
|
||||
* |<------tRDV---->| |
|
||||
* ->| |<-tRELEASE
|
||||
*
|
||||
* r -- allowed to pull high via the resitor when slave writes a 1-bit
|
||||
*
|
||||
*/
|
||||
static int
|
||||
owc_gpiobus_read_data(device_t dev, struct ow_timing *t, int *bit)
|
||||
{
|
||||
struct owc_gpiobus_softc *sc;
|
||||
int error, sample;
|
||||
sbintime_t then, now;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
error = GETBUS(sc);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
/* Force low for t_lowr microseconds */
|
||||
then = sbinuptime();
|
||||
OUTPIN(sc);
|
||||
LOW(sc);
|
||||
DELAY(t->t_lowr);
|
||||
|
||||
/*
|
||||
* Slave is supposed to hold the line low for t_rdv microseconds for 0
|
||||
* and immediately float it high for a 1. This is measured from the
|
||||
* master's pushing the line low.
|
||||
*/
|
||||
INPIN(sc);
|
||||
critical_enter();
|
||||
do {
|
||||
now = sbinuptime();
|
||||
GETPIN(sc, &sample);
|
||||
} while ((now - then) / SBT_1US < t->t_rdv + 2 && sample == 0);
|
||||
critical_exit();
|
||||
|
||||
if ((now - then) / SBT_1NS < t->t_rdv * 1000)
|
||||
*bit = 1;
|
||||
else
|
||||
*bit = 0;
|
||||
|
||||
/* Wait out the rest of t_slot */
|
||||
do {
|
||||
now = sbinuptime();
|
||||
} while ((now - then) / SBT_1US < t->t_slot);
|
||||
|
||||
RELBUS(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* RESET AND PRESENCE PULSE (see owll_if.m for timings) From Figure 4-4 AN-937
|
||||
*
|
||||
* |<---------tRSTH------------>|
|
||||
* High RRRM | | RRRRRRRS | RRRR RRM
|
||||
* M | |R| |S | R M
|
||||
* M| R | | S |R M
|
||||
* Low MMMMMMMM MMMMMM| | | SSSSSSSSSS MMMMMM
|
||||
* |<----tRSTL--->| | |<-tPDL---->|
|
||||
* | ->| |<-tR | |
|
||||
* |<tPDH>|
|
||||
*
|
||||
* Note: for Regular Speed operations, tRSTL + tR should be less than 960us to
|
||||
* avoid interferring with other devices on the bus
|
||||
*/
|
||||
static int
|
||||
owc_gpiobus_reset_and_presence(device_t dev, struct ow_timing *t, int *bit)
|
||||
{
|
||||
struct owc_gpiobus_softc *sc;
|
||||
int error;
|
||||
int buf = -1;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
error = GETBUS(sc);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
|
||||
/*
|
||||
* Read the current state of the bus. The steady state of an idle bus is
|
||||
* high. Badly wired buses that are missing the required pull up, or
|
||||
* that have a short circuit to ground cause all kinds of mischief when
|
||||
* we try to read them later. Return EIO and release the bus if the bus
|
||||
* is currently low.
|
||||
*/
|
||||
INPIN(sc);
|
||||
GETPIN(sc, &buf);
|
||||
if (buf == 0) {
|
||||
*bit = -1;
|
||||
RELBUS(sc);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
critical_enter();
|
||||
|
||||
/* Force low */
|
||||
OUTPIN(sc);
|
||||
LOW(sc);
|
||||
DELAY(t->t_rstl);
|
||||
|
||||
/* Allow resistor to float line high and then wait for reset pulse */
|
||||
INPIN(sc);
|
||||
DELAY(t->t_pdh + t->t_pdl / 2);
|
||||
|
||||
/* Read presence pulse */
|
||||
GETPIN(sc, &buf);
|
||||
*bit = !!buf;
|
||||
|
||||
critical_exit();
|
||||
|
||||
DELAY(t->t_rsth - (t->t_pdh + t->t_pdl / 2)); /* Timing not critical for this one */
|
||||
|
||||
/*
|
||||
* Read the state of the bus after we've waited past the end of the rest
|
||||
* window. It should return to high. If it is low, then we have some
|
||||
* problem and should abort the reset.
|
||||
*/
|
||||
GETPIN(sc, &buf);
|
||||
if (buf == 0) {
|
||||
*bit = -1;
|
||||
RELBUS(sc);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
RELBUS(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static devclass_t owc_gpiobus_devclass;
|
||||
|
||||
static device_method_t owc_gpiobus_methods[] = {
|
||||
/* Device interface */
|
||||
#ifdef FDT
|
||||
DEVMETHOD(device_identify, owc_gpiobus_identify),
|
||||
#endif
|
||||
DEVMETHOD(device_probe, owc_gpiobus_probe),
|
||||
DEVMETHOD(device_attach, owc_gpiobus_attach),
|
||||
DEVMETHOD(device_detach, owc_gpiobus_detach),
|
||||
|
||||
DEVMETHOD(owll_write_one, owc_gpiobus_write_one),
|
||||
DEVMETHOD(owll_write_zero, owc_gpiobus_write_zero),
|
||||
DEVMETHOD(owll_read_data, owc_gpiobus_read_data),
|
||||
DEVMETHOD(owll_reset_and_presence, owc_gpiobus_reset_and_presence),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t owc_gpiobus_driver = {
|
||||
"owc",
|
||||
owc_gpiobus_methods,
|
||||
sizeof(struct owc_gpiobus_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(owc_gpiobus_fdt, gpiobus, owc_gpiobus_driver, owc_gpiobus_devclass, 0, 0);
|
||||
MODULE_DEPEND(owc_gpiobus_fdt, ow, 1, 1, 1);
|
54
sys/dev/ow/owll.h
Normal file
54
sys/dev/ow/owll.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 M. Warner Losh <imp@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef DEV_OW_OWLL_H
|
||||
#define DEV_OW_OWLL_H 1
|
||||
|
||||
/*
|
||||
* Generalized parameters for the mode of operation in the bus. All units
|
||||
* are in nanoseconds, and assume that all timings are < 4s.
|
||||
* See owll_if.m for timings, and refer to AN937 for details.
|
||||
*/
|
||||
struct ow_timing
|
||||
{
|
||||
uint32_t t_slot; /* Slot time */
|
||||
uint32_t t_low0; /* Time low for a 0 bit. */
|
||||
uint32_t t_low1; /* Time low for a 1 bit. */
|
||||
uint32_t t_lowr; /* Time slave holds line down per bit */
|
||||
uint32_t t_release; /* Time after t_rdv to float high */
|
||||
uint32_t t_rec; /* After sample before M low */
|
||||
uint32_t t_rdv; /* Time to poll the bit after M low */
|
||||
uint32_t t_rstl; /* Time M low on reset */
|
||||
uint32_t t_rsth; /* Time M high on reset */
|
||||
uint32_t t_pdl; /* Time S low on reset */
|
||||
uint32_t t_pdh; /* Time R high after M low on reset */
|
||||
};
|
||||
|
||||
#include "owll_if.h"
|
||||
|
||||
#endif /* DEV_OW_OWLL_H */
|
158
sys/dev/ow/owll_if.m
Normal file
158
sys/dev/ow/owll_if.m
Normal file
@ -0,0 +1,158 @@
|
||||
#-
|
||||
# Copyright (c) 2015 M. Warner Losh <imp@freebsd.org>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <dev/ow/owll.h>
|
||||
|
||||
INTERFACE owll;
|
||||
|
||||
#
|
||||
# Dallas Semiconductor 1-Wire bus Link Layer (owll)
|
||||
#
|
||||
# See Maxim Application Note AN937: Book of iButton Standards for the
|
||||
# 1-Wire protocol specification.
|
||||
# http://pdfserv.maximintegrated.com/en/an/AN937.pdf
|
||||
#
|
||||
# Note: 1-Wire is a registered trademark of Maxim Integrated Products, Inc.
|
||||
#
|
||||
# This file provides an interface to the logical layer of the protocol.
|
||||
# Although the first implementation is done with GPIO bit banging, some
|
||||
# SoCs have a 1-Wire controller with more smarts or hardware offload.
|
||||
# Maxim datasheets also describe how to use UARTs to generate timing,
|
||||
# as well as both usb and i2c 1-Wire controllers.
|
||||
#
|
||||
# Chapter 4 has all the electrical timing diagrams that make up the link
|
||||
# layer of this protocol.
|
||||
#
|
||||
# Two speed classes are defined: Regular speed and Overdrive speed.
|
||||
# It is the responsibility of a device implementing the owll(9) interface
|
||||
# to ensure that the timings are met:
|
||||
#
|
||||
# Regular Overdrive
|
||||
#
|
||||
# 60us <= tSLOT < 120us 6us <= tSLOT <= 16us
|
||||
# 60us <= tLOW0 < tSLOT < 120us 6us <= tLOW0 < tSLOT < 16us
|
||||
# 1us <= tLOW1 < 15us 1us <= tLOW < 2us
|
||||
# 1us < tLOWR < 15us 1us <= tLOWR < 2us
|
||||
# 0 <= tRELEASE < 45us 0 <= tRELEASE < 4us
|
||||
# 1us <= tREC < inf 1us <= tREC < inf
|
||||
# tRDV = 15us tRDV = 2us
|
||||
# 480us <= tRSTL < inf 48us <= tRSTL < 80us
|
||||
# 480us <= tRSTH < inf 48us <= tRSTH < inf
|
||||
# 15us < tPDH < 60us 2us <= tPDH < 6us
|
||||
# 60us < tPDL < 240us 8us <= tPDL < 24us
|
||||
#
|
||||
# In the diagrams below, R is driven by the resistor pullup, M is driven by
|
||||
# the master, and S is driven by the slave / target.
|
||||
#
|
||||
# All of these methods are expected to be called from the "network"/bus layer
|
||||
# for doing its operations. See 1wn_if.m for those.
|
||||
#
|
||||
# Note: This is the polling / busy-wait interface. An interrupt-based interface
|
||||
# may be different. But an interrupt-based, non-blocking interface can be tricky.
|
||||
#
|
||||
# Only the owbus should talk to this interface.
|
||||
#
|
||||
|
||||
# WRITE-ONE (see above for timings) From Figure 4-1 AN-937
|
||||
#
|
||||
# |<---------tSLOT---->|<-tREC->|
|
||||
# High RRRRM | RRRRRRRRRRRR|RRRRRRRRM
|
||||
# M | R | | | M
|
||||
# M| R | | | M
|
||||
# Low MMMMMMM | | | MMMMMM...
|
||||
# |<-tLOW1->| | |
|
||||
# |<------15us--->| |
|
||||
# |<--------60us---->|
|
||||
#
|
||||
#
|
||||
METHOD int write_one {
|
||||
device_t lldev; /* Link Level device (eg bridge) */
|
||||
struct ow_timing *timing; /* timing values */
|
||||
};
|
||||
|
||||
|
||||
# WRITE-ZERO (see above for timings) From Figure 4-2 AN-937
|
||||
#
|
||||
# |<---------tSLOT------>|<-tREC->|
|
||||
# High RRRRM | | |RRRRRRRM
|
||||
# M | | R M
|
||||
# M| | | |R M
|
||||
# Low MMMMMMMMMMMMMMMMMMMMMR MMMMMM...
|
||||
# |<--15us->| | |
|
||||
# |<------60us--->| |
|
||||
# |<-------tLOW0------>|
|
||||
#
|
||||
#
|
||||
METHOD int write_zero {
|
||||
device_t lldev; /* Link Level device (eg bridge) */
|
||||
struct ow_timing *timing; /* timing values */
|
||||
};
|
||||
|
||||
# READ-DATA (see above for timings) From Figure 4-3 AN-937
|
||||
#
|
||||
# |<---------tSLOT------>|<-tREC->|
|
||||
# High RRRRM | rrrrrrrrrrrrrrrRRRRRRRM
|
||||
# M | r | R M
|
||||
# M| r | |R M
|
||||
# Low MMMMMMMSSSSSSSSSSSSSSR MMMMMM...
|
||||
# |<tLOWR>< sample > |
|
||||
# |<------tRDV---->| |
|
||||
# ->| |<-tRELEASE
|
||||
#
|
||||
# r -- allowed to pull high via the resistor when slave writes a 1-bit
|
||||
#
|
||||
METHOD int read_data {
|
||||
device_t lldev; /* Link Level device (eg bridge) */
|
||||
struct ow_timing *timing; /* timing values */
|
||||
int *bit; /* Bit we sampled */
|
||||
};
|
||||
|
||||
# RESET AND PRESENCE PULSE (see above for timings) From Figure 4-4 AN-937
|
||||
#
|
||||
# |<---------tRSTH------------>|
|
||||
# High RRRM | | RRRRRRRS | RRRR RRM
|
||||
# M | |R| |S | R M
|
||||
# M| R | | S |R M
|
||||
# Low MMMMMMMM MMMMMM| | | SSSSSSSSSS MMMMMM
|
||||
# |<----tRSTL--->| | |<-tPDL---->|
|
||||
# | ->| |<-tR | |
|
||||
# |<tPDH>|
|
||||
#
|
||||
# Note: for Regular Speed operations, tRSTL + tR should be less than 960us to
|
||||
# avoid interfering with other devives on the bus.
|
||||
#
|
||||
# Returns errors associating with acquiring the bus, or EIO to indicate
|
||||
# that the bus was low during the RRRR time where it should have been
|
||||
# pulled high. The present field is always updated, even on error.
|
||||
#
|
||||
METHOD int reset_and_presence {
|
||||
device_t lldev; /* Link level device (eg bridge) */
|
||||
struct ow_timing *timing; /* timing values */
|
||||
int *present; /* 0 = slave 1 = no slave -1 = bus error */
|
||||
};
|
106
sys/dev/ow/own.h
Normal file
106
sys/dev/ow/own.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 M. Warner Losh <imp@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef DEV_OW_OWN_H
|
||||
#define DEV_OW_OWN_H 1
|
||||
|
||||
#include "own_if.h"
|
||||
|
||||
|
||||
#define READ_ROM 0x33
|
||||
#define MATCH_ROM 0x55
|
||||
#define SKIP_ROM 0xcc
|
||||
#define ALARM_SEARCH 0xec
|
||||
#define SEARCH_ROM 0xf0
|
||||
|
||||
static inline int
|
||||
own_send_command(device_t pdev, struct ow_cmd *cmd)
|
||||
{
|
||||
device_t ndev = device_get_parent(pdev);
|
||||
|
||||
return OWN_SEND_COMMAND(ndev, pdev, cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* How args for own_acquire_bus
|
||||
*/
|
||||
#define OWN_WAIT 1
|
||||
#define OWN_DONTWAIT 2
|
||||
|
||||
static inline int
|
||||
own_acquire_bus(device_t pdev, int how)
|
||||
{
|
||||
device_t ndev = device_get_parent(pdev);
|
||||
|
||||
return OWN_ACQUIRE_BUS(ndev, pdev, how);
|
||||
}
|
||||
|
||||
static inline void
|
||||
own_release_bus(device_t pdev)
|
||||
{
|
||||
device_t ndev = device_get_parent(pdev);
|
||||
|
||||
OWN_RELEASE_BUS(ndev, pdev);
|
||||
}
|
||||
|
||||
static inline uint8_t
|
||||
own_crc(device_t pdev, uint8_t *buffer, size_t len)
|
||||
{
|
||||
device_t ndev = device_get_parent(pdev);
|
||||
|
||||
return OWN_CRC(ndev, pdev, buffer, len);
|
||||
}
|
||||
|
||||
static inline void
|
||||
own_self_command(device_t pdev, struct ow_cmd *cmd, uint8_t xpt_cmd)
|
||||
{
|
||||
uint8_t *mep;
|
||||
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
mep = ow_get_romid(pdev);
|
||||
cmd->rom_cmd[0] = MATCH_ROM;
|
||||
memcpy(&cmd->rom_cmd[1], mep, sizeof(romid_t));
|
||||
cmd->rom_len = 1 + sizeof(romid_t);
|
||||
cmd->xpt_cmd[0] = xpt_cmd;
|
||||
cmd->xpt_len = 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
own_command_wait(device_t pdev, struct ow_cmd *cmd)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = own_acquire_bus(pdev, OWN_WAIT);
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
rv = own_send_command(pdev, cmd);
|
||||
own_release_bus(pdev);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif /* DEV_OW_OWLL_H */
|
78
sys/dev/ow/own_if.m
Normal file
78
sys/dev/ow/own_if.m
Normal file
@ -0,0 +1,78 @@
|
||||
#-
|
||||
# Copyright (c) 2015 M. Warner Losh <imp@freebsd.org>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <dev/ow/ow.h>
|
||||
|
||||
INTERFACE own;
|
||||
|
||||
#
|
||||
# Dallas Semiconductor 1-Wire bus network and transport layer (own)
|
||||
#
|
||||
# See Maxim Application Note AN937: Book of iButton Standards for the
|
||||
# 1-Wire protocol specification.
|
||||
# http://pdfserv.maximintegrated.com/en/an/AN937.pdf
|
||||
#
|
||||
# Note: 1-Wire is a registered trademark of Maxim Integrated Products, Inc.
|
||||
#
|
||||
|
||||
#
|
||||
# Send a command up the stack.
|
||||
#
|
||||
METHOD int send_command {
|
||||
device_t ndev; /* Network (bus) level device */
|
||||
device_t pdev; /* Device to send command for */
|
||||
struct ow_cmd *cmd; /* Pointer to filled in command */
|
||||
};
|
||||
|
||||
#
|
||||
# Grab exclusive use of the bus (advisory)
|
||||
#
|
||||
METHOD int acquire_bus {
|
||||
device_t ndev;
|
||||
device_t pdev;
|
||||
int how;
|
||||
};
|
||||
|
||||
#
|
||||
# Release exclusive use of the bus (advisory)
|
||||
#
|
||||
METHOD void release_bus {
|
||||
device_t ndev;
|
||||
device_t pdev;
|
||||
};
|
||||
|
||||
#
|
||||
# Compute a CRC for a given range of bytes
|
||||
#
|
||||
METHOD uint8_t crc {
|
||||
device_t ndev;
|
||||
device_t pdev;
|
||||
uint8_t *buffer;
|
||||
size_t len;
|
||||
};
|
@ -270,6 +270,7 @@ SUBDIR= \
|
||||
${_nxge} \
|
||||
${_opensolaris} \
|
||||
oce \
|
||||
ow \
|
||||
${_padlock} \
|
||||
${_padlock_rng} \
|
||||
patm \
|
||||
|
8
sys/modules/ow/Makefile
Normal file
8
sys/modules/ow/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SYSDIR?=${.CURDIR}/../..
|
||||
.include "${SYSDIR}/conf/kern.opts.mk"
|
||||
|
||||
SUBDIR = ow owc ow_temp
|
||||
|
||||
.include <bsd.subdir.mk>
|
9
sys/modules/ow/ow/Makefile
Normal file
9
sys/modules/ow/ow/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../dev/ow
|
||||
|
||||
KMOD= ow
|
||||
SRCS= ow.c
|
||||
SRCS+= own_if.c own_if.h owll_if.c owll_if.h bus_if.h device_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
9
sys/modules/ow/ow_temp/Makefile
Normal file
9
sys/modules/ow/ow_temp/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../dev/ow
|
||||
|
||||
KMOD= ow_temp
|
||||
SRCS= ow_temp.c
|
||||
SRCS+= own_if.h bus_if.h device_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
10
sys/modules/ow/owc/Makefile
Normal file
10
sys/modules/ow/owc/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../dev/ow
|
||||
|
||||
KMOD= owc
|
||||
SRCS= owc_gpiobus.c
|
||||
SRCS+= gpio_if.h gpiobus_if.h owll_if.h ofw_bus_if.h bus_if.h device_if.h
|
||||
SRCS+= opt_platform.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
Loading…
Reference in New Issue
Block a user