diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2022-05-19 13:55:43 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2022-05-19 13:55:43 +0200 |
commit | 764fdbaba337e3b58f31ce7b177c4e7c0ba2088d (patch) | |
tree | 954b7c40be6beb5ab6ca9158840e93873cc43427 /drivers | |
parent | 28889ccbfe785c59bfaa7c39985c376b697e2331 (diff) | |
parent | 747146a3eb186fb7101f1aaab53d9188dc41bfbb (diff) | |
download | barebox-764fdbaba337e3b58f31ce7b177c4e7c0ba2088d.tar.gz barebox-764fdbaba337e3b58f31ce7b177c4e7c0ba2088d.tar.xz |
Merge branch 'for-next/misc'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/disk_ata_drive.c | 23 | ||||
-rw-r--r-- | drivers/i2c/busses/Kconfig | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-cadence.c | 453 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-rockchip.c | 13 | ||||
-rw-r--r-- | drivers/phy/rockchip/phy-rockchip-naneng-combphy.c | 19 | ||||
-rw-r--r-- | drivers/serial/serial_ns16550.c | 14 | ||||
-rw-r--r-- | drivers/spi/Kconfig | 6 | ||||
-rw-r--r-- | drivers/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/spi/spi-sifive.c | 521 | ||||
-rw-r--r-- | drivers/usb/dwc3/core.c | 50 | ||||
-rw-r--r-- | drivers/video/Kconfig | 2 | ||||
-rw-r--r-- | drivers/video/omap.c | 3 |
13 files changed, 1060 insertions, 54 deletions
diff --git a/drivers/ata/disk_ata_drive.c b/drivers/ata/disk_ata_drive.c index f36e06328c..7df0879b19 100644 --- a/drivers/ata/disk_ata_drive.c +++ b/drivers/ata/disk_ata_drive.c @@ -80,9 +80,9 @@ static void __maybe_unused ata_dump_id(uint16_t *id) ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); printf("Product model number: %s\n\r", product); - /* Total sectors of device */ + /* Total sectors of device */ n_sectors = ata_id_n_sectors(id); - printf("Capablity: %lld sectors\n\r", n_sectors); + printf("Capacity: %lld sectors\n\r", n_sectors); printf ("id[49]: capabilities = 0x%04x\n" "id[53]: field valid = 0x%04x\n" @@ -95,12 +95,14 @@ static void __maybe_unused ata_dump_id(uint16_t *id) id[ATA_ID_PIO_MODES], id[ATA_ID_QUEUE_DEPTH]); - printf ("id[76]: sata capablity = 0x%04x\n" + printf ("id[76]: sata capabilities 1 = 0x%04x\n" + "id[77]: sata capabilities 2 = 0x%04x\n" "id[78]: sata features supported = 0x%04x\n" - "id[79]: sata features enable = 0x%04x\n", - id[76], /* FIXME */ - id[78], /* FIXME */ - id[79]); /* FIXME */ + "id[79]: sata features enabled = 0x%04x\n", + id[ATA_ID_SATA_CAPAB_1], + id[ATA_ID_SATA_CAPAB_2], + id[ATA_ID_SATA_FEAT_SUPP], + id[ATA_ID_SATA_FEAT_ENABLE]); printf ("id[80]: major version = 0x%04x\n" "id[81]: minor version = 0x%04x\n" @@ -108,12 +110,13 @@ static void __maybe_unused ata_dump_id(uint16_t *id) "id[83]: command set supported 2 = 0x%04x\n" "id[84]: command set extension = 0x%04x\n", id[ATA_ID_MAJOR_VER], - id[81], /* FIXME */ + id[ATA_ID_MINOR_VER], id[ATA_ID_COMMAND_SET_1], id[ATA_ID_COMMAND_SET_2], id[ATA_ID_CFSSE]); - printf ("id[85]: command set enable 1 = 0x%04x\n" - "id[86]: command set enable 2 = 0x%04x\n" + + printf ("id[85]: command set enabled 1 = 0x%04x\n" + "id[86]: command set enabled 2 = 0x%04x\n" "id[87]: command set default = 0x%04x\n" "id[88]: udma = 0x%04x\n" "id[93]: hardware reset result = 0x%04x\n", diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index d4e74552b7..58f8656067 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -70,4 +70,12 @@ config I2C_RK3X Say Y here to include support for the I2C adapter in Rockchip RK3xxx SoCs. +config I2C_CADENCE + bool "Cadence I2C adapter" + depends on HAVE_CLK + depends on ARCH_ZYNQMP || COMPILE_TEST + help + Say Y here to include support for the Cadence I2C host controller found + in Zynq UltraScale+ MPSoCs. + endmenu diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index d6273f3d86..a8661f605e 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_DESIGNWARE) += i2c-designware.o obj-$(CONFIG_I2C_STM32) += i2c-stm32.o obj-$(CONFIG_I2C_RK3X) += i2c-rockchip.o +obj-$(CONFIG_I2C_CADENCE) += i2c-cadence.o diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c new file mode 100644 index 0000000000..5537efff23 --- /dev/null +++ b/drivers/i2c/busses/i2c-cadence.c @@ -0,0 +1,453 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * I2C bus driver for the Cadence I2C host controller (master only). + * + * Partly based on the driver in the Linux kernel + * Copyright (C) 2009 - 2014 Xilinx, Inc. + * + * Copyright (C) 2022 Matthias Fend <matthias.fend@emfend.at> + */ + +#include <common.h> +#include <i2c/i2c.h> +#include <linux/iopoll.h> +#include <errno.h> +#include <linux/err.h> +#include <driver.h> +#include <io.h> +#include <linux/clk.h> +#include <regmap.h> + +struct __packed i2c_regs { + u32 control; + u32 status; + u32 address; + u32 data; + u32 interrupt_status; + u32 transfer_size; + u32 slave_mon_pause; + u32 time_out; + u32 interrupt_mask; + u32 interrupt_enable; + u32 interrupt_disable; + u32 glitch_filter; +}; + +/* Control register fields */ +#define CDNS_I2C_CONTROL_RW BIT(0) +#define CDNS_I2C_CONTROL_MS BIT(1) +#define CDNS_I2C_CONTROL_NEA BIT(2) +#define CDNS_I2C_CONTROL_ACKEN BIT(3) +#define CDNS_I2C_CONTROL_HOLD BIT(4) +#define CDNS_I2C_CONTROL_SLVMON BIT(5) +#define CDNS_I2C_CONTROL_CLR_FIFO BIT(6) +#define CDNS_I2C_CONTROL_DIV_B_SHIFT 8 +#define CDNS_I2C_CONTROL_DIV_B_MASK (0x3F << CDNS_I2C_CONTROL_DIV_B_SHIFT) +#define CDNS_I2C_CONTROL_DIV_A_SHIFT 14 +#define CDNS_I2C_CONTROL_DIV_A_MASK (0x03 << CDNS_I2C_CONTROL_DIV_A_SHIFT) + +#define CDNS_I2C_CONTROL_DIV_B_MAX 64 +#define CDNS_I2C_CONTROL_DIV_A_MAX 4 + +/* Status register fields */ +#define CDNS_I2C_STATUS_RXRW BIT(3) +#define CDNS_I2C_STATUS_RXDV BIT(5) +#define CDNS_I2C_STATUS_TXDV BIT(6) +#define CDNS_I2C_STATUS_RXOVF BIT(7) +#define CDNS_I2C_STATUS_BA BIT(8) + +/* Address register fields */ +#define CDNS_I2C_ADDRESS_MASK 0x3FF + +/* Interrupt register fields */ +#define CDNS_I2C_INTERRUPT_COMP BIT(0) +#define CDNS_I2C_INTERRUPT_DATA BIT(1) +#define CDNS_I2C_INTERRUPT_NACK BIT(2) +#define CDNS_I2C_INTERRUPT_TO BIT(3) +#define CDNS_I2C_INTERRUPT_SLVRDY BIT(4) +#define CDNS_I2C_INTERRUPT_RXOVF BIT(5) +#define CDNS_I2C_INTERRUPT_TXOVF BIT(6) +#define CDNS_I2C_INTERRUPT_RXUNF BIT(7) +#define CDNS_I2C_INTERRUPT_ARBLOST BIT(9) + +#define CDNS_I2C_INTERRUPTS_MASK_MASTER (CDNS_I2C_INTERRUPT_COMP | \ + CDNS_I2C_INTERRUPT_DATA | \ + CDNS_I2C_INTERRUPT_NACK | \ + CDNS_I2C_INTERRUPT_RXOVF | \ + CDNS_I2C_INTERRUPT_TXOVF | \ + CDNS_I2C_INTERRUPT_RXUNF | \ + CDNS_I2C_INTERRUPT_ARBLOST) + +#define CDNS_I2C_INTERRUPTS_MASK_ALL (CDNS_I2C_INTERRUPT_COMP | \ + CDNS_I2C_INTERRUPT_DATA | \ + CDNS_I2C_INTERRUPT_NACK | \ + CDNS_I2C_INTERRUPT_TO | \ + CDNS_I2C_INTERRUPT_SLVRDY | \ + CDNS_I2C_INTERRUPT_RXOVF | \ + CDNS_I2C_INTERRUPT_TXOVF | \ + CDNS_I2C_INTERRUPT_RXUNF | \ + CDNS_I2C_INTERRUPT_ARBLOST) + +#define CDNS_I2C_FIFO_DEPTH 16 +#define CDNS_I2C_TRANSFER_SIZE_MAX 255 +#define CDNS_I2C_TRANSFER_SIZE (CDNS_I2C_TRANSFER_SIZE_MAX - 3) + +#define I2C_TIMEOUT_US (100 * USEC_PER_MSEC) + +struct cdns_i2c { + struct i2c_adapter adapter; + struct clk *clk; + struct i2c_regs *regs; + bool bus_hold_flag; +}; + +static void cdns_i2c_reset_hardware(struct cdns_i2c *i2c) +{ + struct i2c_regs *regs = i2c->regs; + u32 regval; + + writel(CDNS_I2C_INTERRUPTS_MASK_ALL, ®s->interrupt_disable); + + regval = readl(®s->control); + regval &= ~CDNS_I2C_CONTROL_HOLD; + regval |= CDNS_I2C_CONTROL_CLR_FIFO; + writel(regval, ®s->control); + + writel(0xFF, ®s->time_out); + + writel(0, ®s->transfer_size); + + regval = readl(®s->interrupt_status); + writel(regval, ®s->interrupt_status); + + regval = readl(®s->status); + writel(regval, ®s->status); + + writel(0, ®s->control); +} + +static void cdns_i2c_setup_master(struct cdns_i2c *i2c) +{ + u32 control; + + control = readl(&i2c->regs->control); + control |= CDNS_I2C_CONTROL_MS | CDNS_I2C_CONTROL_ACKEN | + CDNS_I2C_CONTROL_NEA; + writel(control, &i2c->regs->control); + + writel(CDNS_I2C_INTERRUPTS_MASK_MASTER, &i2c->regs->interrupt_enable); +} + +static void cdns_i2c_clear_hold_flag(struct cdns_i2c *i2c) +{ + u32 control; + + control = readl(&i2c->regs->control); + if (control & CDNS_I2C_CONTROL_HOLD) + writel(control & ~CDNS_I2C_CONTROL_HOLD, &i2c->regs->control); +} + +static bool cdns_i2c_is_busy(struct cdns_i2c *i2c) +{ + return readl(&i2c->regs->status) & CDNS_I2C_STATUS_BA; +} + +static int cdns_i2c_hw_error(struct cdns_i2c *i2c) +{ + u32 isr_status; + + isr_status = readl(&i2c->regs->interrupt_status); + + if (isr_status & CDNS_I2C_INTERRUPT_NACK) + return -EREMOTEIO; + + if (isr_status & + (CDNS_I2C_INTERRUPT_ARBLOST | CDNS_I2C_INTERRUPT_RXOVF)) + return -EAGAIN; + + return 0; +} + +static int cdns_i2c_wait_for_completion(struct cdns_i2c *i2c) +{ + int err; + u32 isr_status; + const u32 isr_mask = + (CDNS_I2C_INTERRUPT_COMP | CDNS_I2C_INTERRUPT_NACK | + CDNS_I2C_INTERRUPT_ARBLOST); + + err = readl_poll_timeout(&i2c->regs->interrupt_status, isr_status, + isr_status & isr_mask, I2C_TIMEOUT_US); + + if (err) + return -ETIMEDOUT; + + return cdns_i2c_hw_error(i2c); +} + +/* + * Find best clock divisors + * + * f = finput / (22 x (div_a + 1) x (div_b + 1)) + */ +static int cdns_i2c_calc_divs(u32 *f, u32 input_clk, u32 *a, u32 *b) +{ + ulong fscl = *f, best_fscl = *f, actual_fscl, temp; + uint div_a, div_b, calc_div_a = 0, calc_div_b = 0; + uint last_error, current_error; + + temp = input_clk / (22 * fscl); + + if (!temp || + (temp > (CDNS_I2C_CONTROL_DIV_A_MAX * CDNS_I2C_CONTROL_DIV_B_MAX))) + return -EINVAL; + + last_error = -1; + for (div_a = 0; div_a < CDNS_I2C_CONTROL_DIV_A_MAX; div_a++) { + div_b = DIV_ROUND_UP(input_clk, 22 * fscl * (div_a + 1)); + + if ((div_b < 1) || (div_b > CDNS_I2C_CONTROL_DIV_B_MAX)) + continue; + div_b--; + + actual_fscl = input_clk / (22 * (div_a + 1) * (div_b + 1)); + + if (actual_fscl > fscl) + continue; + + current_error = ((actual_fscl > fscl) ? (actual_fscl - fscl) : + (fscl - actual_fscl)); + + if (last_error > current_error) { + calc_div_a = div_a; + calc_div_b = div_b; + best_fscl = actual_fscl; + last_error = current_error; + } + } + + *a = calc_div_a; + *b = calc_div_b; + *f = best_fscl; + + return 0; +} + +static int cdns_i2c_set_clk(struct cdns_i2c *i2c, u32 scl_rate) +{ + u32 i2c_rate; + u32 control; + u32 div_a, div_b; + int err; + + i2c_rate = clk_get_rate(i2c->clk); + + err = cdns_i2c_calc_divs(&scl_rate, i2c_rate, &div_a, &div_b); + if (err) + return err; + + control = readl(&i2c->regs->control); + control &= ~(CDNS_I2C_CONTROL_DIV_B_MASK | CDNS_I2C_CONTROL_DIV_A_MASK); + control |= (div_b << CDNS_I2C_CONTROL_DIV_B_SHIFT) | + (div_a << CDNS_I2C_CONTROL_DIV_A_SHIFT); + writel(control, &i2c->regs->control); + + return err; +} + +static int cdns_i2c_read(struct cdns_i2c *i2c, uchar chip, uchar *buf, + uint buf_len) +{ + struct i2c_regs *regs = i2c->regs; + u32 control; + int err; + + control = readl(®s->control); + control |= CDNS_I2C_CONTROL_RW | CDNS_I2C_CONTROL_CLR_FIFO; + if (i2c->bus_hold_flag || (buf_len > CDNS_I2C_FIFO_DEPTH)) + control |= CDNS_I2C_CONTROL_HOLD; + writel(control, ®s->control); + + do { + uint bytes_to_receive; + u32 isr_status; + u64 start_time; + + isr_status = readl(®s->interrupt_status); + writel(isr_status, ®s->interrupt_status); + + if (buf_len > CDNS_I2C_TRANSFER_SIZE) + bytes_to_receive = CDNS_I2C_TRANSFER_SIZE; + else + bytes_to_receive = buf_len; + + buf_len -= bytes_to_receive; + + writel(bytes_to_receive, ®s->transfer_size); + writel(chip & CDNS_I2C_ADDRESS_MASK, ®s->address); + + start_time = get_time_ns(); + while (bytes_to_receive) { + err = cdns_i2c_hw_error(i2c); + if (err) + goto i2c_exit; + + if (is_timeout(start_time, + (I2C_TIMEOUT_US * USECOND))) { + err = -ETIMEDOUT; + goto i2c_exit; + } + + if (readl(®s->status) & CDNS_I2C_STATUS_RXDV) { + *buf++ = readl(®s->data); + bytes_to_receive--; + } + } + + } while (buf_len); + + err = cdns_i2c_wait_for_completion(i2c); + +i2c_exit: + if (!i2c->bus_hold_flag) + cdns_i2c_clear_hold_flag(i2c); + + return err; +} + +static int cdns_i2c_write(struct cdns_i2c *i2c, uchar chip, uchar *buf, + uint buf_len) +{ + struct i2c_regs *regs = i2c->regs; + u32 control; + u32 isr_status; + bool start_transfer; + int err; + + control = readl(®s->control); + control &= ~CDNS_I2C_CONTROL_RW; + control |= CDNS_I2C_CONTROL_CLR_FIFO; + if (i2c->bus_hold_flag || (buf_len > CDNS_I2C_FIFO_DEPTH)) + control |= CDNS_I2C_CONTROL_HOLD; + writel(control, ®s->control); + + isr_status = readl(®s->interrupt_status); + writel(isr_status, ®s->interrupt_status); + + start_transfer = true; + do { + uint bytes_to_send; + + bytes_to_send = + CDNS_I2C_FIFO_DEPTH - readl(®s->transfer_size); + + if (buf_len < bytes_to_send) + bytes_to_send = buf_len; + + buf_len -= bytes_to_send; + + while (bytes_to_send--) + writel(*buf++, ®s->data); + + if (start_transfer) { + writel(chip & CDNS_I2C_ADDRESS_MASK, ®s->address); + start_transfer = false; + } + + err = cdns_i2c_wait_for_completion(i2c); + if (err) + goto i2c_exit; + + } while (buf_len); + +i2c_exit: + if (!i2c->bus_hold_flag) + cdns_i2c_clear_hold_flag(i2c); + + return err; +} + +static int cdns_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg, + int nmsgs) +{ + struct cdns_i2c *i2c = container_of(adapter, struct cdns_i2c, adapter); + int i; + int err; + + if (cdns_i2c_is_busy(i2c)) + return -EBUSY; + + for (i = 0; i < nmsgs; i++) { + i2c->bus_hold_flag = i < (nmsgs - 1); + + if (msg->flags & I2C_M_RD) { + err = cdns_i2c_read(i2c, msg->addr, msg->buf, msg->len); + } else { + err = cdns_i2c_write(i2c, msg->addr, msg->buf, + msg->len); + } + + if (err) + return err; + + msg++; + } + + return nmsgs; +} + +static int cdns_i2c_probe(struct device_d *dev) +{ + struct device_node *np = dev->device_node; + struct resource *iores; + struct cdns_i2c *i2c; + u32 bitrate; + int err; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + i2c = xzalloc(sizeof(*i2c)); + + dev->priv = i2c; + i2c->regs = IOMEM(iores->start); + + i2c->clk = clk_get(dev, NULL); + if (IS_ERR(i2c->clk)) + return PTR_ERR(i2c->clk); + + err = clk_enable(i2c->clk); + if (err) + return err; + + i2c->adapter.master_xfer = cdns_i2c_xfer; + i2c->adapter.nr = dev->id; + i2c->adapter.dev.parent = dev; + i2c->adapter.dev.device_node = np; + + cdns_i2c_reset_hardware(i2c); + + bitrate = 100000; + of_property_read_u32(np, "clock-frequency", &bitrate); + + err = cdns_i2c_set_clk(i2c, bitrate); + if (err) + return err; + + cdns_i2c_setup_master(i2c); + + return i2c_add_numbered_adapter(&i2c->adapter); +} + +static const struct of_device_id cdns_i2c_match[] = { + { .compatible = "cdns,i2c-r1p14" }, + {}, +}; + +static struct driver_d cdns_i2c_driver = { + .name = "cdns-i2c", + .of_compatible = cdns_i2c_match, + .probe = cdns_i2c_probe, +}; +coredevice_platform_driver(cdns_i2c_driver); diff --git a/drivers/i2c/busses/i2c-rockchip.c b/drivers/i2c/busses/i2c-rockchip.c index 4990735a4b..ca33905335 100644 --- a/drivers/i2c/busses/i2c-rockchip.c +++ b/drivers/i2c/busses/i2c-rockchip.c @@ -375,15 +375,17 @@ i2c_exit: return err; } -static int rockchip_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg, +static int rockchip_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) { struct rk_i2c *i2c = to_rk_i2c(adapter); struct device_d *dev = &adapter->dev; - int ret; + int i, ret = 0; dev_dbg(dev, "i2c_xfer: %d messages\n", nmsgs); - for (; nmsgs > 0; nmsgs--, msg++) { + for (i = 0; i < nmsgs; i++) { + struct i2c_msg *msg = &msgs[i]; + dev_dbg(dev, "i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); if (msg->flags & I2C_M_RD) { ret = rk_i2c_read(i2c, msg->addr, 0, 0, msg->buf, @@ -395,14 +397,15 @@ static int rockchip_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg, if (ret) { dev_dbg(dev, "i2c_write: error sending: %pe\n", ERR_PTR(ret)); - return -EREMOTEIO; + ret = -EREMOTEIO; + break; } } rk_i2c_send_stop_bit(i2c); rk_i2c_disable(i2c); - return 0; + return ret < 0 ? ret : nmsgs; } static int rk_i2c_probe(struct device_d *dev) diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c index 445703ecd8..2d86d86334 100644 --- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c @@ -83,7 +83,6 @@ struct rockchip_combphy_priv { struct regmap *pipe_grf; struct regmap *phy_grf; struct phy *phy; - struct reset_control *apb_rst; struct reset_control *phy_rst; const struct rockchip_combphy_cfg *cfg; }; @@ -317,17 +316,7 @@ static int rockchip_combphy_parse_dt(struct device_d *dev, param_write(priv->pipe_grf, &phy_cfg->grfcfg->pipe_sgmii_mac_sel, true); - priv->apb_rst = reset_control_get(dev, "combphy-apb"); - if (IS_ERR(priv->apb_rst)) { - ret = PTR_ERR(priv->apb_rst); - - if (ret != -EPROBE_DEFER) - dev_warn(dev, "failed to get apb reset\n"); - - return ret; - } - - priv->phy_rst = reset_control_get(dev, "combphy"); + priv->phy_rst = reset_control_get(dev, NULL); if (IS_ERR(priv->phy_rst)) { ret = PTR_ERR(priv->phy_rst); @@ -579,9 +568,9 @@ static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = { }; static const struct clk_bulk_data rk3568_clks[] = { - { .id = "refclk" }, - { .id = "apbclk" }, - { .id = "pipe_clk" }, + { .id = "ref" }, + { .id = "apb" }, + { .id = "pipe" }, }; static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c index 464ae1aebc..f93a89ab95 100644 --- a/drivers/serial/serial_ns16550.c +++ b/drivers/serial/serial_ns16550.c @@ -366,11 +366,6 @@ static __maybe_unused struct ns16550_drvdata jz_drvdata = { .init_port = ns16550_jz_init_port, }; -static __maybe_unused struct ns16550_drvdata tegra_drvdata = { - .init_port = ns16550_serial_init_port, - .linux_console_name = "ttyS", -}; - static __maybe_unused struct ns16550_drvdata rpi_drvdata = { .init_port = rpi_init_port, .linux_console_name = "ttyS", @@ -528,6 +523,9 @@ static struct of_device_id ns16550_serial_dt_ids[] = { }, { .compatible = "marvell,armada-38x-uart", .data = &ns16550_drvdata, + }, { + .compatible = "nvidia,tegra20-uart", + .data = &ns16550_drvdata, }, #if IS_ENABLED(CONFIG_ARCH_OMAP) { @@ -541,12 +539,6 @@ static struct of_device_id ns16550_serial_dt_ids[] = { .data = &omap_drvdata, }, #endif -#if IS_ENABLED(CONFIG_ARCH_TEGRA) - { - .compatible = "nvidia,tegra20-uart", - .data = &tegra_drvdata, - }, -#endif #if IS_ENABLED(CONFIG_MACH_MIPS_XBURST) { .compatible = "ingenic,jz4740-uart", diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 7df7561718..8935feb97b 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -124,6 +124,12 @@ config SPI_NXP_FLEXSPI This controller does not support generic SPI messages and only supports the high-level SPI memory interface. +config SPI_SIFIVE + tristate "SiFive SPI controller" + depends on SOC_SIFIVE || COMPILE_TEST + help + This exposes the SPI controller IP from SiFive. + endif endmenu diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 64c8e2645a..3455eea869 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_DRIVER_SPI_DSPI) += dspi_spi.o obj-$(CONFIG_SPI_ZYNQ_QSPI) += zynq_qspi.o obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o obj-$(CONFIG_DRIVER_SPI_STM32) += stm32_spi.o +obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c new file mode 100644 index 0000000000..713bcc0c3b --- /dev/null +++ b/drivers/spi/spi-sifive.c @@ -0,0 +1,521 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 SiFive, Inc. + * Copyright 2019 Bhargav Shah <bhargavshah1988@gmail.com> + * + * SiFive SPI controller driver (master mode only) + */ + +#include <common.h> +#include <linux/clk.h> +#include <driver.h> +#include <init.h> +#include <errno.h> +#include <linux/reset.h> +#include <spi/spi.h> +#include <linux/spi/spi-mem.h> +#include <linux/bitops.h> +#include <clock.h> +#include <gpio.h> +#include <of_gpio.h> +#include <linux/bitfield.h> +#include <linux/iopoll.h> +#include <linux/log2.h> + +#define SIFIVE_SPI_MAX_CS 32 + +#define SIFIVE_SPI_DEFAULT_DEPTH 8 +#define SIFIVE_SPI_DEFAULT_BITS 8 + +/* register offsets */ +#define SIFIVE_SPI_REG_SCKDIV 0x00 /* Serial clock divisor */ +#define SIFIVE_SPI_REG_SCKMODE 0x04 /* Serial clock mode */ +#define SIFIVE_SPI_REG_CSID 0x10 /* Chip select ID */ +#define SIFIVE_SPI_REG_CSDEF 0x14 /* Chip select default */ +#define SIFIVE_SPI_REG_CSMODE 0x18 /* Chip select mode */ +#define SIFIVE_SPI_REG_DELAY0 0x28 /* Delay control 0 */ +#define SIFIVE_SPI_REG_DELAY1 0x2c /* Delay control 1 */ +#define SIFIVE_SPI_REG_FMT 0x40 /* Frame format */ +#define SIFIVE_SPI_REG_TXDATA 0x48 /* Tx FIFO data */ +#define SIFIVE_SPI_REG_RXDATA 0x4c /* Rx FIFO data */ +#define SIFIVE_SPI_REG_TXMARK 0x50 /* Tx FIFO watermark */ +#define SIFIVE_SPI_REG_RXMARK 0x54 /* Rx FIFO watermark */ +#define SIFIVE_SPI_REG_FCTRL 0x60 /* SPI flash interface control */ +#define SIFIVE_SPI_REG_FFMT 0x64 /* SPI flash instruction format */ +#define SIFIVE_SPI_REG_IE 0x70 /* Interrupt Enable Register */ +#define SIFIVE_SPI_REG_IP 0x74 /* Interrupt Pendings Register */ + +/* sckdiv bits */ +#define SIFIVE_SPI_SCKDIV_DIV_MASK 0xfffU + +/* sckmode bits */ +#define SIFIVE_SPI_SCKMODE_PHA BIT(0) +#define SIFIVE_SPI_SCKMODE_POL BIT(1) +#define SIFIVE_SPI_SCKMODE_MODE_MASK (SIFIVE_SPI_SCKMODE_PHA | \ + SIFIVE_SPI_SCKMODE_POL) + +/* csmode bits */ +#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U +#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U +#define SIFIVE_SPI_CSMODE_MODE_OFF 3U + +/* delay0 bits */ +#define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU +#define SIFIVE_SPI_DELAY0_SCKCS(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16) + +/* delay1 bits */ +#define SIFIVE_SPI_DELAY1_INTERCS(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU +#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) + +/* fmt bits */ +#define SIFIVE_SPI_FMT_PROTO_SINGLE 0U +#define SIFIVE_SPI_FMT_PROTO_DUAL 1U +#define SIFIVE_SPI_FMT_PROTO_QUAD 2U +#define SIFIVE_SPI_FMT_PROTO_MASK 3U +#define SIFIVE_SPI_FMT_ENDIAN BIT(2) +#define SIFIVE_SPI_FMT_DIR BIT(3) +#define SIFIVE_SPI_FMT_LEN(x) ((u32)(x) << 16) +#define SIFIVE_SPI_FMT_LEN_MASK (0xfU << 16) + +/* txdata bits */ +#define SIFIVE_SPI_TXDATA_DATA_MASK 0xffU +#define SIFIVE_SPI_TXDATA_FULL BIT(31) + +/* rxdata bits */ +#define SIFIVE_SPI_RXDATA_DATA_MASK 0xffU +#define SIFIVE_SPI_RXDATA_EMPTY BIT(31) + +/* ie and ip bits */ +#define SIFIVE_SPI_IP_TXWM BIT(0) +#define SIFIVE_SPI_IP_RXWM BIT(1) + +/* format protocol */ +#define SIFIVE_SPI_PROTO_QUAD 4 /* 4 lines I/O protocol transfer */ +#define SIFIVE_SPI_PROTO_DUAL 2 /* 2 lines I/O protocol transfer */ +#define SIFIVE_SPI_PROTO_SINGLE 1 /* 1 line I/O protocol transfer */ + +#define SPI_XFER_BEGIN 0x01 /* Assert CS before transfer */ +#define SPI_XFER_END 0x02 /* Deassert CS after transfer */ + +struct sifive_spi { + struct spi_controller ctlr; + void __iomem *regs; /* base address of the registers */ + u32 fifo_depth; + u32 bits_per_word; + u32 cs_inactive; /* Level of the CS pins when inactive*/ + u32 freq; + u8 fmt_proto; +}; + +static inline struct sifive_spi *to_sifive_spi(struct spi_controller *ctlr) +{ + return container_of(ctlr, struct sifive_spi, ctlr); +} + +static void sifive_spi_prep_device(struct sifive_spi *spi, + struct spi_device *spi_dev) +{ + /* Update the chip select polarity */ + if (spi_dev->mode & SPI_CS_HIGH) + spi->cs_inactive &= ~BIT(spi_dev->chip_select); + else + spi->cs_inactive |= BIT(spi_dev->chip_select); + writel(spi->cs_inactive, spi->regs + SIFIVE_SPI_REG_CSDEF); + + /* Select the correct device */ + writel(spi_dev->chip_select, spi->regs + SIFIVE_SPI_REG_CSID); +} + +static void sifive_spi_set_cs(struct sifive_spi *spi, + struct spi_device *spi_dev) +{ + u32 cs_mode = SIFIVE_SPI_CSMODE_MODE_HOLD; + + if (spi_dev->mode & SPI_CS_HIGH) + cs_mode = SIFIVE_SPI_CSMODE_MODE_AUTO; + + writel(cs_mode, spi->regs + SIFIVE_SPI_REG_CSMODE); +} + +static void sifive_spi_clear_cs(struct sifive_spi *spi) +{ + writel(SIFIVE_SPI_CSMODE_MODE_AUTO, spi->regs + SIFIVE_SPI_REG_CSMODE); +} + +static void sifive_spi_prep_transfer(struct sifive_spi *spi, + struct spi_device *spi_dev, + u8 *rx_ptr) +{ + u32 cr; + + /* Modify the SPI protocol mode */ + cr = readl(spi->regs + SIFIVE_SPI_REG_FMT); + + /* Bits per word ? */ + cr &= ~SIFIVE_SPI_FMT_LEN_MASK; + cr |= SIFIVE_SPI_FMT_LEN(spi->bits_per_word); + + /* LSB first? */ + cr &= ~SIFIVE_SPI_FMT_ENDIAN; + if (spi_dev->mode & SPI_LSB_FIRST) + cr |= SIFIVE_SPI_FMT_ENDIAN; + + /* Number of wires ? */ + cr &= ~SIFIVE_SPI_FMT_PROTO_MASK; + switch (spi->fmt_proto) { + case SIFIVE_SPI_PROTO_QUAD: + cr |= SIFIVE_SPI_FMT_PROTO_QUAD; + break; + case SIFIVE_SPI_PROTO_DUAL: + cr |= SIFIVE_SPI_FMT_PROTO_DUAL; + break; + default: + cr |= SIFIVE_SPI_FMT_PROTO_SINGLE; + break; + } + + /* SPI direction in/out ? */ + cr &= ~SIFIVE_SPI_FMT_DIR; + if (!rx_ptr) + cr |= SIFIVE_SPI_FMT_DIR; + + writel(cr, spi->regs + SIFIVE_SPI_REG_FMT); +} + +static void sifive_spi_rx(struct sifive_spi *spi, u8 *rx_ptr) +{ + u32 data; + + do { + data = readl(spi->regs + SIFIVE_SPI_REG_RXDATA); + } while (data & SIFIVE_SPI_RXDATA_EMPTY); + + if (rx_ptr) + *rx_ptr = data & SIFIVE_SPI_RXDATA_DATA_MASK; +} + +static void sifive_spi_tx(struct sifive_spi *spi, const u8 *tx_ptr) +{ + u32 data; + u8 tx_data = (tx_ptr) ? *tx_ptr & SIFIVE_SPI_TXDATA_DATA_MASK : + SIFIVE_SPI_TXDATA_DATA_MASK; + + do { + data = readl(spi->regs + SIFIVE_SPI_REG_TXDATA); + } while (data & SIFIVE_SPI_TXDATA_FULL); + + writel(tx_data, spi->regs + SIFIVE_SPI_REG_TXDATA); +} + +static int sifive_spi_wait(struct sifive_spi *spi, u32 mask) +{ + u32 val; + + return readl_poll_timeout(spi->regs + SIFIVE_SPI_REG_IP, val, + (val & mask) == mask, 100 * USEC_PER_MSEC); +} + +static int sifive_spi_transfer_one(struct spi_device *spi_dev, unsigned int nbytes, + const void *dout, void *din) +{ + struct sifive_spi *spi = to_sifive_spi(spi_dev->controller); + const u8 *tx_ptr = dout; + u8 *rx_ptr = din; + int ret; + + sifive_spi_prep_transfer(spi, spi_dev, rx_ptr); + + while (nbytes) { + unsigned int n_words = min(nbytes, spi->fifo_depth); + unsigned int tx_words, rx_words; + + /* Enqueue n_words for transmission */ + for (tx_words = 0; tx_words < n_words; tx_words++) { + if (!tx_ptr) + sifive_spi_tx(spi, NULL); + else + sifive_spi_tx(spi, tx_ptr++); + } + + if (rx_ptr) { + /* Wait for transmission + reception to complete */ + writel(n_words - 1, spi->regs + SIFIVE_SPI_REG_RXMARK); + ret = sifive_spi_wait(spi, SIFIVE_SPI_IP_RXWM); + if (ret) + return ret; + + /* Read out all the data from the RX FIFO */ + for (rx_words = 0; rx_words < n_words; rx_words++) + sifive_spi_rx(spi, rx_ptr++); + } else { + /* Wait for transmission to complete */ + ret = sifive_spi_wait(spi, SIFIVE_SPI_IP_TXWM); + if (ret) + return ret; + } + + nbytes -= n_words; + } + + return 0; +} + +static int sifive_spi_transfer(struct spi_device *spi_dev, struct spi_message *msg) +{ + struct spi_controller *ctlr = spi_dev->controller; + struct sifive_spi *spi = to_sifive_spi(ctlr); + struct spi_transfer *t; + int ret = 0; + + if (list_empty(&msg->transfers)) + return 0; + + msg->actual_length = 0; + + sifive_spi_prep_device(spi, spi_dev); + sifive_spi_set_cs(spi, spi_dev); + + dev_dbg(ctlr->dev, "transfer start actual_length=%i\n", msg->actual_length); + list_for_each_entry(t, &msg->transfers, transfer_list) { + dev_dbg(ctlr->dev, " xfer %p: len %u tx %p rx %p\n", + t, t->len, t->tx_buf, t->rx_buf); + + ret = sifive_spi_transfer_one(spi_dev, t->len, + t->tx_buf, t->rx_buf); + if (ret < 0) + goto out; + msg->actual_length += t->len; + } + dev_dbg(ctlr->dev, "transfer done actual_length=%i\n", msg->actual_length); + +out: + sifive_spi_clear_cs(spi); + return ret; +} + +static int sifive_spi_exec_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct spi_device *spi_dev = mem->spi; + struct device_d *dev = &spi_dev->dev; + struct sifive_spi *spi = spi_controller_get_devdata(spi_dev->controller); + u8 opcode = op->cmd.opcode; + int ret; + + spi->fmt_proto = op->cmd.buswidth; + + sifive_spi_prep_device(spi, spi_dev); + sifive_spi_set_cs(spi, spi_dev); + + /* send the opcode */ + ret = sifive_spi_transfer_one(spi_dev, 1, &opcode, NULL); + if (ret < 0) { + dev_err(dev, "failed to xfer opcode\n"); + goto out; + } + + if (!op->addr.nbytes && !op->data.nbytes) + goto out; + + /* send the addr + dummy */ + if (op->addr.nbytes) { + int i, op_len = op->addr.nbytes + op->dummy.nbytes; + u8 *op_buf; + + op_buf = malloc(op_len); + if (!op_buf) { + ret = -ENOMEM; + goto out; + } + + /* fill address */ + for (i = 0; i < op->addr.nbytes; i++) + op_buf[i] = op->addr.val >> + (8 * (op->addr.nbytes - i - 1)); + + /* fill dummy */ + memset(op_buf + op->addr.nbytes, 0xff, op->dummy.nbytes); + + spi->fmt_proto = op->addr.buswidth; + + ret = sifive_spi_transfer_one(spi_dev, op_len, op_buf, NULL); + free(op_buf); + if (ret < 0) { + dev_err(dev, "failed to xfer addr + dummy\n"); + goto out; + } + } + + /* send/received the data */ + if (op->data.nbytes) { + const void *tx_buf = NULL; + void *rx_buf = NULL; + + if (op->data.dir == SPI_MEM_DATA_IN) + rx_buf = op->data.buf.in; + else + tx_buf = op->data.buf.out; + + spi->fmt_proto = op->data.buswidth; + + ret = sifive_spi_transfer_one(spi_dev, op->data.nbytes, + tx_buf, rx_buf); + if (ret) { + dev_err(dev, "failed to xfer data\n"); + goto out; + } + } + +out: + sifive_spi_clear_cs(spi); + return ret; +} + +static void sifive_spi_set_speed(struct sifive_spi *spi, uint speed) +{ + u32 scale; + + if (speed > spi->freq) + speed = spi->freq; + + /* Cofigure max speed */ + scale = (DIV_ROUND_UP(spi->freq >> 1, speed) - 1) + & SIFIVE_SPI_SCKDIV_DIV_MASK; + writel(scale, spi->regs + SIFIVE_SPI_REG_SCKDIV); +} + +static void sifive_spi_set_mode(struct sifive_spi *spi, uint mode) +{ + u32 cr; + + /* Switch clock mode bits */ + cr = readl(spi->regs + SIFIVE_SPI_REG_SCKMODE) & + ~SIFIVE_SPI_SCKMODE_MODE_MASK; + if (mode & SPI_CPHA) + cr |= SIFIVE_SPI_SCKMODE_PHA; + if (mode & SPI_CPOL) + cr |= SIFIVE_SPI_SCKMODE_POL; + + writel(cr, spi->regs + SIFIVE_SPI_REG_SCKMODE); +} + +static int sifive_spi_setup(struct spi_device *spi_dev) +{ + struct sifive_spi *spi = to_sifive_spi(spi_dev->controller); + + sifive_spi_set_mode(spi, spi_dev->mode); + sifive_spi_set_speed(spi, spi_dev->max_speed_hz); + + return 0; +} + +static void sifive_spi_init_hw(struct sifive_spi *spi) +{ + struct device_d *dev = spi->ctlr.dev; + u32 cs_bits; + + /* probe the number of CS lines */ + spi->cs_inactive = readl(spi->regs + SIFIVE_SPI_REG_CSDEF); + writel(0xffffffffU, spi->regs + SIFIVE_SPI_REG_CSDEF); + cs_bits = readl(spi->regs + SIFIVE_SPI_REG_CSDEF); + writel(spi->cs_inactive, spi->regs + SIFIVE_SPI_REG_CSDEF); + if (!cs_bits) { + dev_warn(dev, "Could not auto probe CS lines\n"); + return; + } + + spi->ctlr.num_chipselect = ilog2(cs_bits) + 1; + if (spi->ctlr.num_chipselect > SIFIVE_SPI_MAX_CS) { + dev_warn(dev, "Invalid number of spi slaves\n"); + return; + } + + /* Watermark interrupts are disabled by default */ + writel(0, spi->regs + SIFIVE_SPI_REG_IE); + + /* Default watermark FIFO threshold values */ + writel(1, spi->regs + SIFIVE_SPI_REG_TXMARK); + writel(0, spi->regs + SIFIVE_SPI_REG_RXMARK); + + /* Set CS/SCK Delays and Inactive Time to defaults */ + writel(SIFIVE_SPI_DELAY0_CSSCK(1) | SIFIVE_SPI_DELAY0_SCKCS(1), + spi->regs + SIFIVE_SPI_REG_DELAY0); + writel(SIFIVE_SPI_DELAY1_INTERCS(1) | SIFIVE_SPI_DELAY1_INTERXFR(0), + spi->regs + SIFIVE_SPI_REG_DELAY1); + + /* Exit specialized memory-mapped SPI flash mode */ + writel(0, spi->regs + SIFIVE_SPI_REG_FCTRL); +} + +static const struct spi_controller_mem_ops sifive_spi_mem_ops = { + .exec_op = sifive_spi_exec_op, +}; + +static void sifive_spi_dt_probe(struct sifive_spi *spi) +{ + struct device_node *node = spi->ctlr.dev->device_node; + + spi->fifo_depth = SIFIVE_SPI_DEFAULT_DEPTH; + of_property_read_u32(node, "sifive,fifo-depth", &spi->fifo_depth); + + spi->bits_per_word = SIFIVE_SPI_DEFAULT_BITS; + of_property_read_u32(node, "sifive,max-bits-per-word", &spi->bits_per_word); +} + +static int sifive_spi_probe(struct device_d *dev) +{ + struct sifive_spi *spi; + struct resource *iores; + struct spi_controller *ctlr; + struct clk *clkdev; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + spi = xzalloc(sizeof(*spi)); + + spi->regs = IOMEM(iores->start); + if (!spi->regs) + return -ENODEV; + + ctlr = &spi->ctlr; + ctlr->dev = dev; + + ctlr->setup = sifive_spi_setup; + ctlr->transfer = sifive_spi_transfer; + ctlr->mem_ops = &sifive_spi_mem_ops; + + ctlr->bus_num = -1; + + spi_controller_set_devdata(ctlr, spi); + + sifive_spi_dt_probe(spi); + + clkdev = clk_get(dev, NULL); + if (IS_ERR(clkdev)) + return PTR_ERR(clkdev); + + spi->freq = clk_get_rate(clkdev); + + /* init the sifive spi hw */ + sifive_spi_init_hw(spi); + + return spi_register_master(ctlr); +} + +static const struct of_device_id sifive_spi_ids[] = { + { .compatible = "sifive,spi0" }, + { /* sentinel */ } +}; + +static struct driver_d sifive_spi_driver = { + .name = "sifive_spi", + .probe = sifive_spi_probe, + .of_compatible = sifive_spi_ids, +}; +coredevice_platform_driver(sifive_spi_driver); diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index fd0ec754e0..30aaef90ac 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -23,6 +23,11 @@ #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */ +struct dwc3_match_data { + const struct clk_bulk_data *clks; + const int num_clks; +}; + /** * dwc3_get_dr_mode - Validates and sets dr_mode * @dwc: pointer to our context structure @@ -326,12 +331,6 @@ err0: return ret; } -static const struct clk_bulk_data dwc3_core_clks[] = { - { .id = "ref" }, - { .id = "bus_early" }, - { .id = "suspend" }, -}; - /* * dwc3_frame_length_adjustment - Adjusts frame length if required * @dwc3: Pointer to our controller context structure @@ -1098,20 +1097,23 @@ static void dwc3_coresoft_reset(struct dwc3 *dwc) static int dwc3_probe(struct device_d *dev) { + const struct dwc3_match_data *match; struct dwc3 *dwc; int ret; dwc = xzalloc(sizeof(*dwc)); dev->priv = dwc; - dwc->clks = xmemdup(dwc3_core_clks, sizeof(dwc3_core_clks)); + match = device_get_match_data(dev); + dwc->clks = xmemdup(match->clks, match->num_clks * + sizeof(struct clk_bulk_data)); dwc->dev = dev; dwc->regs = dev_get_mem_region(dwc->dev, 0) + DWC3_GLOBALS_REGS_START; dwc3_get_properties(dwc); if (dev->device_node) { - dwc->num_clks = ARRAY_SIZE(dwc3_core_clks); + dwc->num_clks = match->num_clks; if (of_find_property(dev->device_node, "clocks", NULL)) { ret = clk_bulk_get(dev, dwc->num_clks, dwc->clks); @@ -1176,12 +1178,40 @@ static void dwc3_remove(struct device_d *dev) clk_bulk_put(dwc->num_clks, dwc->clks); } +static const struct clk_bulk_data dwc3_core_clks[] = { + { .id = "ref" }, + { .id = "bus_early" }, + { .id = "suspend" }, +}; + +static const struct dwc3_match_data dwc3_default = { + .clks = dwc3_core_clks, + .num_clks = ARRAY_SIZE(dwc3_core_clks), +}; + +static const struct clk_bulk_data dwc3_core_clks_rk3568[] = { + { .id = "ref_clk" }, + { .id = "bus_clk" }, + { .id = "suspend_clk" }, +}; + +static const struct dwc3_match_data dwc3_rk3568 = { + .clks = dwc3_core_clks_rk3568, + .num_clks = ARRAY_SIZE(dwc3_core_clks_rk3568), +}; + static const struct of_device_id of_dwc3_match[] = { { - .compatible = "snps,dwc3" + .compatible = "snps,dwc3", + .data = &dwc3_default, + }, + { + .compatible = "synopsys,dwc3", + .data = &dwc3_default, }, { - .compatible = "synopsys,dwc3" + .compatible = "rockchip,rk3568-dwc3", + .data = &dwc3_rk3568, }, { }, }; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index dcdc6c2135..a20b7bbee9 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -75,7 +75,7 @@ config DRIVER_VIDEO_S3C24XX config DRIVER_VIDEO_OMAP bool "OMAP framebuffer driver" - depends on ARCH_OMAP4 + depends on ARCH_OMAP4 || COMPILE_TEST help Add support for OMAP Display Controller. Currently this driver only supports OMAP4 SoCs in DISPC parallel mode on diff --git a/drivers/video/omap.c b/drivers/video/omap.c index 62c51a1dfc..ca41ab36fc 100644 --- a/drivers/video/omap.c +++ b/drivers/video/omap.c @@ -20,8 +20,7 @@ #include <clock.h> #include <linux/err.h> -#include <mach/omap4-silicon.h> -#include <mach/omap-fb.h> +#include <video/omap-fb.h> #include <mmu.h> |