#if CONFIG_IS_ENABLED(DM_I2C)
# include <i2c.h>
#endif
+#if CONFIG_IS_ENABLED(DM_SPI)
+# include <spi.h>
+#endif
#include <net/dsa.h>
#include <asm-generic/gpio.h>
#define MMD_SETUP(mode, dev) (((u16)(mode) << PORT_MMD_OP_MODE_S) | (dev))
#define REG_PORT_PHY_MMD_INDEX_DATA 0x011C
+/* SPI specific define (opcodes) */
+#define KSZ_SPI_OP_RD 3
+#define KSZ_SPI_OP_WR 2
+
+#define KSZ9477_SPI_ADDR_SHIFT 24
+#define KSZ9477_SPI_ADDR_ALIGN 3
+#define KSZ9477_SPI_TURNAROUND_SHIFT 5
+
/**
* struct ksz_phy_ops - low-level KSZ bus operations
*/
};
#endif
+#if CONFIG_IS_ENABLED(DM_SPI)
+/**
+ * ksz_spi_xfer() - only used for 8/16/32 bits bus access
+ *
+ * @dev: The SPI slave device which will be sending/receiving the data.
+ * @reg: register address.
+ * @out: Pointer to a string of bits to send out. The bits are
+ * held in a byte array and are sent MSB first.
+ * @in: Pointer to a string of bits that will be filled in.
+ * @len: number of bytes to read.
+ *
+ * Return: 0 on success, not 0 on failure
+ */
+static int ksz_spi_xfer(struct udevice *dev, u32 reg, const u8 *out,
+ u8 *in, u16 len)
+{
+ int ret;
+ u32 addr = 0;
+ u8 opcode;
+
+ if (in && out) {
+ printf("%s: can't do full duplex\n", __func__);
+ return -EINVAL;
+ }
+
+ if (len > 4 || len == 0) {
+ printf("%s: only 8/16/32 bits bus access supported\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ ret = dm_spi_claim_bus(dev);
+ if (ret < 0) {
+ printf("%s: could not claim bus\n", __func__);
+ return ret;
+ }
+
+ opcode = (in ? KSZ_SPI_OP_RD : KSZ_SPI_OP_WR);
+
+ /* The actual device address space is 16 bits (A15 - A0),
+ * so the values of address bits A23 - A16 in the SPI
+ * command/address phase are “don't care”.
+ */
+ addr |= opcode << (KSZ9477_SPI_ADDR_SHIFT + KSZ9477_SPI_TURNAROUND_SHIFT);
+ addr |= reg << KSZ9477_SPI_TURNAROUND_SHIFT;
+
+ addr = __swab32(addr);
+
+ ret = dm_spi_xfer(dev, 32, &addr, NULL, SPI_XFER_BEGIN);
+ if (ret) {
+ printf("%s ERROR: dm_spi_xfer addr (%u)\n", __func__, ret);
+ goto release_bus;
+ }
+
+ ret = dm_spi_xfer(dev, len * 8, out, in, SPI_XFER_END);
+ if (ret) {
+ printf("%s ERROR: dm_spi_xfer data (%u)\n", __func__, ret);
+ goto release_bus;
+ }
+
+release_bus:
+ /* If an error occurred, release the chip by deasserting the CS */
+ if (ret < 0)
+ dm_spi_xfer(dev, 0, NULL, NULL, SPI_XFER_END);
+
+ dm_spi_release_bus(dev);
+
+ return ret;
+}
+
+static inline int ksz_spi_read(struct udevice *dev, u32 reg, u8 *val, int len)
+{
+ return ksz_spi_xfer(dev, reg, NULL, val, len);
+}
+
+static inline int ksz_spi_write(struct udevice *dev, u32 reg, u8 *val, int len)
+{
+ return ksz_spi_xfer(dev, reg, val, NULL, len);
+}
+
+static struct ksz_phy_ops phy_spi_ops = {
+ .read = ksz_spi_read,
+ .write = ksz_spi_write,
+};
+#endif
+
static inline int ksz_read8(struct udevice *dev, u32 reg, u8 *val)
{
struct ksz_dsa_priv *priv = dev_get_priv(dev);
}
break;
}
+#endif
+#if CONFIG_IS_ENABLED(DM_SPI)
+ case UCLASS_SPI: {
+ ksz_ops_register(dev, &phy_spi_ops);
+ break;
+ }
#endif
default:
dev_err(dev, "invalid parent bus (%s)\n",