Merge branch 'for-next/mips'
Conflicts: arch/mips/boards/loongson-ls1b/serial.c
This commit is contained in:
commit
8fb1d4e075
|
@ -1,2 +1 @@
|
|||
obj-y += ram.o
|
||||
obj-y += serial.o
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <sizes.h>
|
||||
#include <asm/memory.h>
|
||||
|
||||
static int mem_init(void)
|
||||
{
|
||||
mips_add_ram0(SZ_64M);
|
||||
|
||||
return 0;
|
||||
}
|
||||
mem_initcall(mem_init);
|
|
@ -1,22 +1,10 @@
|
|||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <ns16550.h>
|
||||
|
||||
#include <mach/loongson1.h>
|
||||
|
||||
static struct NS16550_plat serial_plat = {
|
||||
.clock = 83000000,
|
||||
.shift = 0,
|
||||
};
|
||||
|
||||
static int console_init(void)
|
||||
{
|
||||
barebox_set_model("Loongson Tech LS1B Demo Board");
|
||||
barebox_set_hostname("ls1b");
|
||||
|
||||
add_ns16550_device(DEVICE_ID_DYNAMIC, KSEG1ADDR(LS1X_UART2_BASE),
|
||||
8, IORESOURCE_MEM | IORESOURCE_MEM_8BIT, &serial_plat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
console_initcall(console_init);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
CONFIG_BUILTIN_DTB=y
|
||||
CONFIG_BUILTIN_DTB_NAME="loongson-ls1b"
|
||||
CONFIG_MACH_MIPS_LOONGSON=y
|
||||
CONFIG_PBL_IMAGE=y
|
||||
CONFIG_STACK_SIZE=0x7000
|
||||
|
@ -36,7 +38,11 @@ CONFIG_CMD_IOMEM=y
|
|||
CONFIG_FLEXIBLE_BOOTARGS=y
|
||||
CONFIG_CMD_RESET=y
|
||||
CONFIG_CMD_GO=y
|
||||
CONFIG_CMD_OFTREE=y
|
||||
CONFIG_CMD_OF_PROPERTY=y
|
||||
CONFIG_CMD_OF_NODE=y
|
||||
CONFIG_CMD_TIMEOUT=y
|
||||
CONFIG_OFDEVICE=y
|
||||
# CONFIG_SPI is not set
|
||||
CONFIG_ZLIB=y
|
||||
CONFIG_BZLIB=y
|
||||
|
|
|
@ -14,16 +14,21 @@ CONFIG_CMD_MEMINFO=y
|
|||
CONFIG_CMD_IOMEM=y
|
||||
CONFIG_CMD_MM=y
|
||||
CONFIG_CMD_SHA1SUM=y
|
||||
CONFIG_CMD_FLASH=y
|
||||
# CONFIG_CMD_BOOTM is not set
|
||||
CONFIG_CMD_RESET=y
|
||||
CONFIG_CMD_GO=y
|
||||
CONFIG_CMD_OFTREE=y
|
||||
CONFIG_CMD_OF_PROPERTY=y
|
||||
CONFIG_CMD_OF_NODE=y
|
||||
CONFIG_CMD_SPI=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_OFDEVICE=y
|
||||
CONFIG_DRIVER_SERIAL_AR933X=y
|
||||
# CONFIG_SPI is not set
|
||||
CONFIG_DRIVER_SPI_ATH79=y
|
||||
CONFIG_MTD=y
|
||||
# CONFIG_MTD_OOB_DEVICE is not set
|
||||
CONFIG_MTD_M25P80=y
|
||||
CONFIG_MD5=y
|
||||
CONFIG_SHA224=y
|
||||
CONFIG_SHA256=y
|
||||
|
|
|
@ -22,5 +22,11 @@
|
|||
reg = <0xb8050000 0x48>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
spi: spi@bf000000{
|
||||
compatible = "qca,ath79-spi";
|
||||
reg = <0xbf000000 0x01000000>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include "ls1b.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Loongson Tech LS1B Demo Board";
|
||||
compatible = "loongson,ls1b";
|
||||
|
||||
memory {
|
||||
reg = <0x00000000 0x4000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&serial2 {
|
||||
status = "okay";
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
#include "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
soc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
device_type = "soc";
|
||||
ranges;
|
||||
|
||||
serial0: serial@bfe40000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0xbfe40000 0x8>;
|
||||
reg-shift = <0>;
|
||||
clock-frequency = <83000000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial1: serial@bfe44000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0xbfe44000 0x8>;
|
||||
reg-shift = <0>;
|
||||
clock-frequency = <83000000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial2: serial@bfe48000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0xbfe48000 0x8>;
|
||||
reg-shift = <0>;
|
||||
clock-frequency = <83000000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial3: serial@bfe4c000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0xbfe4c000 0x8>;
|
||||
reg-shift = <0>;
|
||||
clock-frequency = <83000000>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -14,3 +14,23 @@
|
|||
&serial0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi {
|
||||
num-chipselects = <1>;
|
||||
status = "okay";
|
||||
|
||||
/* Spansion S25FL032PIF SPI flash */
|
||||
spiflash: m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "m25p80";
|
||||
spi-max-frequency = <104000000>;
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
spiflash = &spiflash;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -10,6 +10,10 @@ config DRIVER_SPI_ALTERA
|
|||
bool "Altera SPI Master driver"
|
||||
depends on NIOS2
|
||||
|
||||
config DRIVER_SPI_ATH79
|
||||
bool "Atheros AR71XX/AR724X/AR913X/AR933X SPI controller driver"
|
||||
depends on MACH_MIPS_ATH79
|
||||
|
||||
config DRIVER_SPI_ATMEL
|
||||
bool "Atmel (AT91) SPI Master driver"
|
||||
depends on ARCH_AT91
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
obj-$(CONFIG_SPI) += spi.o
|
||||
obj-$(CONFIG_DRIVER_SPI_ATH79) += ath79_spi.o
|
||||
obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o
|
||||
obj-$(CONFIG_DRIVER_SPI_MVEBU) += mvebu_spi.o
|
||||
obj-$(CONFIG_DRIVER_SPI_MXS) += mxs_spi.o
|
||||
|
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* Copyright (C) 2013, 2014 Antony Pavlov <antonynpavlov@gmail.com>
|
||||
*
|
||||
* This file is part of barebox.
|
||||
* See file CREDITS for list of people who contributed to this project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <driver.h>
|
||||
#include <spi/spi.h>
|
||||
#include <io.h>
|
||||
#include <clock.h>
|
||||
|
||||
struct ath79_spi {
|
||||
struct spi_master master;
|
||||
void __iomem *regs;
|
||||
u32 val;
|
||||
u32 reg_ctrl;
|
||||
};
|
||||
|
||||
#define AR71XX_SPI_REG_FS 0x00 /* Function Select */
|
||||
#define AR71XX_SPI_REG_CTRL 0x04 /* SPI Control */
|
||||
#define AR71XX_SPI_REG_IOC 0x08 /* SPI I/O Control */
|
||||
#define AR71XX_SPI_REG_RDS 0x0c /* Read Data Shift */
|
||||
|
||||
#define AR71XX_SPI_FS_GPIO BIT(0) /* Enable GPIO mode */
|
||||
|
||||
#define AR71XX_SPI_IOC_DO BIT(0) /* Data Out pin */
|
||||
#define AR71XX_SPI_IOC_CLK BIT(8) /* CLK pin */
|
||||
#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n))
|
||||
#define AR71XX_SPI_IOC_CS0 AR71XX_SPI_IOC_CS(0)
|
||||
#define AR71XX_SPI_IOC_CS1 AR71XX_SPI_IOC_CS(1)
|
||||
#define AR71XX_SPI_IOC_CS2 AR71XX_SPI_IOC_CS(2)
|
||||
#define AR71XX_SPI_IOC_CS_ALL (AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | \
|
||||
AR71XX_SPI_IOC_CS2)
|
||||
|
||||
static inline u32 ath79_spi_rr(struct ath79_spi *sp, int reg)
|
||||
{
|
||||
return cpu_readl(sp->regs + reg);
|
||||
}
|
||||
|
||||
static inline void ath79_spi_wr(struct ath79_spi *sp, u32 val, int reg)
|
||||
{
|
||||
cpu_writel(val, sp->regs + reg);
|
||||
}
|
||||
|
||||
static inline void setbits(struct ath79_spi *sp, int bits, int on)
|
||||
{
|
||||
/*
|
||||
* We are the only user of SCSPTR so no locking is required.
|
||||
* Reading bit 2 and 0 in SCSPTR gives pin state as input.
|
||||
* Writing the same bits sets the output value.
|
||||
* This makes regular read-modify-write difficult so we
|
||||
* use sp->val to keep track of the latest register value.
|
||||
*/
|
||||
|
||||
if (on)
|
||||
sp->val |= bits;
|
||||
else
|
||||
sp->val &= ~bits;
|
||||
|
||||
ath79_spi_wr(sp, sp->val, AR71XX_SPI_REG_IOC);
|
||||
}
|
||||
|
||||
static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
|
||||
{
|
||||
return container_of(spi->master, struct ath79_spi, master);
|
||||
}
|
||||
|
||||
static inline void setsck(struct spi_device *spi, int on)
|
||||
{
|
||||
struct ath79_spi *sc = ath79_spidev_to_sp(spi);
|
||||
|
||||
setbits(sc, AR71XX_SPI_IOC_CLK, on);
|
||||
}
|
||||
|
||||
static inline void setmosi(struct spi_device *spi, int on)
|
||||
{
|
||||
struct ath79_spi *sc = ath79_spidev_to_sp(spi);
|
||||
|
||||
setbits(sc, AR71XX_SPI_IOC_DO, on);
|
||||
}
|
||||
|
||||
static inline u32 getmiso(struct spi_device *spi)
|
||||
{
|
||||
struct ath79_spi *sc = ath79_spidev_to_sp(spi);
|
||||
|
||||
return !!((ath79_spi_rr(sc, AR71XX_SPI_REG_RDS) & 1));
|
||||
}
|
||||
|
||||
#include "spi-bitbang-txrx.h"
|
||||
|
||||
static inline void ath79_spi_chipselect(struct ath79_spi *sp, int chipselect)
|
||||
{
|
||||
int off_bits;
|
||||
|
||||
off_bits = 0xffffffff;
|
||||
|
||||
switch (chipselect) {
|
||||
case 0:
|
||||
off_bits &= ~AR71XX_SPI_IOC_CS0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
off_bits &= ~AR71XX_SPI_IOC_CS1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
off_bits &= ~AR71XX_SPI_IOC_CS2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
break;
|
||||
}
|
||||
|
||||
/* by default inactivate chip selects */
|
||||
sp->val |= AR71XX_SPI_IOC_CS_ALL;
|
||||
sp->val &= off_bits;
|
||||
|
||||
ath79_spi_wr(sp, sp->val, AR71XX_SPI_REG_IOC);
|
||||
}
|
||||
|
||||
static int ath79_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
struct spi_master *master = spi->master;
|
||||
struct device_d spi_dev = spi->dev;
|
||||
|
||||
if (spi->bits_per_word != 8) {
|
||||
dev_err(master->dev, "master doesn't support %d bits per word requested by %s\n",
|
||||
spi->bits_per_word, spi_dev.name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((spi->mode & (SPI_CPHA | SPI_CPOL)) != SPI_MODE_0) {
|
||||
dev_err(master->dev, "master doesn't support SPI_MODE%d requested by %s\n",
|
||||
spi->mode & (SPI_CPHA | SPI_CPOL), spi_dev.name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath79_spi_read(struct spi_device *spi, void *buf, size_t nbyte)
|
||||
{
|
||||
ssize_t cnt = 0;
|
||||
u8 *rxf_buf = buf;
|
||||
|
||||
while (cnt < nbyte) {
|
||||
*rxf_buf = bitbang_txrx_be_cpha1(spi, 1000, 1, 0, 8);
|
||||
rxf_buf++;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static int ath79_spi_write(struct spi_device *spi,
|
||||
const void *buf, size_t nbyte)
|
||||
{
|
||||
ssize_t cnt = 0;
|
||||
const u8 *txf_buf = buf;
|
||||
|
||||
while (cnt < nbyte) {
|
||||
bitbang_txrx_be_cpha1(spi, 1000, 1, (u32)*txf_buf, 8);
|
||||
txf_buf++;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath79_spi_transfer(struct spi_device *spi, struct spi_message *mesg)
|
||||
{
|
||||
struct ath79_spi *sc = ath79_spidev_to_sp(spi);
|
||||
struct spi_transfer *t;
|
||||
|
||||
mesg->actual_length = 0;
|
||||
|
||||
/* activate chip select signal */
|
||||
ath79_spi_chipselect(sc, spi->chip_select);
|
||||
|
||||
list_for_each_entry(t, &mesg->transfers, transfer_list) {
|
||||
|
||||
if (t->tx_buf)
|
||||
ath79_spi_write(spi, t->tx_buf, t->len);
|
||||
|
||||
if (t->rx_buf)
|
||||
ath79_spi_read(spi, t->rx_buf, t->len);
|
||||
|
||||
mesg->actual_length += t->len;
|
||||
}
|
||||
|
||||
/* inactivate chip select signal */
|
||||
ath79_spi_chipselect(sc, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath79_spi_enable(struct ath79_spi *sp)
|
||||
{
|
||||
/* enable GPIO mode */
|
||||
ath79_spi_wr(sp, AR71XX_SPI_FS_GPIO, AR71XX_SPI_REG_FS);
|
||||
|
||||
/* save CTRL register */
|
||||
sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
|
||||
sp->val = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
|
||||
|
||||
/* TODO: setup speed? */
|
||||
ath79_spi_wr(sp, 0x43, AR71XX_SPI_REG_CTRL);
|
||||
}
|
||||
|
||||
static void ath79_spi_disable(struct ath79_spi *sp)
|
||||
{
|
||||
/* restore CTRL register */
|
||||
ath79_spi_wr(sp, sp->reg_ctrl, AR71XX_SPI_REG_CTRL);
|
||||
/* disable GPIO mode */
|
||||
ath79_spi_wr(sp, 0, AR71XX_SPI_REG_FS);
|
||||
}
|
||||
|
||||
static int ath79_spi_probe(struct device_d *dev)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct ath79_spi *ath79_spi;
|
||||
|
||||
ath79_spi = xzalloc(sizeof(*ath79_spi));
|
||||
dev->priv = ath79_spi;
|
||||
|
||||
master = &ath79_spi->master;
|
||||
master->dev = dev;
|
||||
|
||||
master->bus_num = dev->id;
|
||||
master->setup = ath79_spi_setup;
|
||||
master->transfer = ath79_spi_transfer;
|
||||
master->num_chipselect = 3;
|
||||
|
||||
if (IS_ENABLED(CONFIG_OFDEVICE)) {
|
||||
struct device_node *node = dev->device_node;
|
||||
u32 num_cs;
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_u32(node, "num-chipselects", &num_cs);
|
||||
if (ret)
|
||||
num_cs = 3;
|
||||
|
||||
if (num_cs > 3) {
|
||||
dev_err(dev, "master doesn't support num-chipselects > 3\n");
|
||||
}
|
||||
|
||||
master->num_chipselect = num_cs;
|
||||
}
|
||||
|
||||
ath79_spi->regs = dev_request_mem_region(dev, 0);
|
||||
|
||||
/* enable gpio mode */
|
||||
ath79_spi_enable(ath79_spi);
|
||||
|
||||
/* inactivate chip select signal */
|
||||
ath79_spi_chipselect(ath79_spi, -1);
|
||||
|
||||
spi_register_master(master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath79_spi_remove(struct device_d *dev)
|
||||
{
|
||||
struct ath79_spi *sp = dev->priv;
|
||||
|
||||
ath79_spi_disable(sp);
|
||||
}
|
||||
|
||||
static __maybe_unused struct of_device_id ath79_spi_dt_ids[] = {
|
||||
{
|
||||
.compatible = "qca,ath79-spi",
|
||||
},
|
||||
{
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static struct driver_d ath79_spi_driver = {
|
||||
.name = "ath79-spi",
|
||||
.probe = ath79_spi_probe,
|
||||
.remove = ath79_spi_remove,
|
||||
.of_compatible = DRV_OF_COMPAT(ath79_spi_dt_ids),
|
||||
};
|
||||
device_platform_driver(ath79_spi_driver);
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Mix this utility code with some glue code to get one of several types of
|
||||
* simple SPI master driver. Two do polled word-at-a-time I/O:
|
||||
*
|
||||
* - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](),
|
||||
* expanding the per-word routines from the inline templates below.
|
||||
*
|
||||
* - Drivers for controllers resembling bare shift registers. Provide
|
||||
* chipselect() and txrx_word[](), with custom setup()/cleanup() methods
|
||||
* that use your controller's clock and chipselect registers.
|
||||
*
|
||||
* Some hardware works well with requests at spi_transfer scope:
|
||||
*
|
||||
* - Drivers leveraging smarter hardware, with fifos or DMA; or for half
|
||||
* duplex (MicroWire) controllers. Provide chipselect() and txrx_bufs(),
|
||||
* and custom setup()/cleanup() methods.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code that knows what GPIO pins do what should have declared four
|
||||
* functions, ideally as inlines, before including this header:
|
||||
*
|
||||
* void setsck(struct spi_device *, int is_on);
|
||||
* void setmosi(struct spi_device *, int is_on);
|
||||
* int getmiso(struct spi_device *);
|
||||
* void spidelay(unsigned);
|
||||
*
|
||||
* setsck()'s is_on parameter is a zero/nonzero boolean.
|
||||
*
|
||||
* setmosi()'s is_on parameter is a zero/nonzero boolean.
|
||||
*
|
||||
* getmiso() is required to return 0 or 1 only. Any other value is invalid
|
||||
* and will result in improper operation.
|
||||
*
|
||||
* A non-inlined routine would call bitbang_txrx_*() routines. The
|
||||
* main loop could easily compile down to a handful of instructions,
|
||||
* especially if the delay is a NOP (to run at peak speed).
|
||||
*
|
||||
* Since this is software, the timings may not be exactly what your board's
|
||||
* chips need ... there may be several reasons you'd need to tweak timings
|
||||
* in these routines, not just to make it faster or slower to match a
|
||||
* particular CPU clock rate.
|
||||
*/
|
||||
|
||||
#define spidelay(nsecs) udelay(nsecs/1000)
|
||||
|
||||
static inline u32
|
||||
bitbang_txrx_be_cpha0(struct spi_device *spi,
|
||||
unsigned nsecs, unsigned cpol,
|
||||
u32 word, u8 bits)
|
||||
{
|
||||
/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
|
||||
|
||||
/* clock starts at inactive polarity */
|
||||
for (word <<= (32 - bits); likely(bits); bits--) {
|
||||
|
||||
/* setup MSB (to slave) on trailing edge */
|
||||
setmosi(spi, word & (1 << 31));
|
||||
spidelay(nsecs); /* T(setup) */
|
||||
|
||||
setsck(spi, !cpol);
|
||||
spidelay(nsecs);
|
||||
|
||||
/* sample MSB (from slave) on leading edge */
|
||||
word <<= 1;
|
||||
word |= getmiso(spi);
|
||||
setsck(spi, cpol);
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
bitbang_txrx_be_cpha1(struct spi_device *spi,
|
||||
unsigned nsecs, unsigned cpol,
|
||||
u32 word, u8 bits)
|
||||
{
|
||||
/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
|
||||
|
||||
/* clock starts at inactive polarity */
|
||||
for (word <<= (32 - bits); likely(bits); bits--) {
|
||||
|
||||
/* setup MSB (to slave) on leading edge */
|
||||
setsck(spi, !cpol);
|
||||
setmosi(spi, word & (1 << 31));
|
||||
spidelay(nsecs); /* T(setup) */
|
||||
|
||||
setsck(spi, cpol);
|
||||
spidelay(nsecs);
|
||||
|
||||
/* sample MSB (from slave) on trailing edge */
|
||||
word <<= 1;
|
||||
word |= getmiso(spi);
|
||||
}
|
||||
return word;
|
||||
}
|
Loading…
Reference in New Issue