F: drivers/soc/fujitsu/a64fx-diag.c
A8293 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/a8293*
AACRAID SCSI RAID DRIVER
F: drivers/iio/accel/adxl372_spi.c
AF9013 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/af9013*
AF9033 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/af9033*
AFFS FILE SYSTEM
F: include/linux/*aio*.h
AIRSPY MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/airspy/
ALACRITECH GIGABIT ETHERNET DRIVER
T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
F: arch/arm/boot/dts/nxp/imx/
F: arch/arm/boot/dts/nxp/mxs/
+ F: arch/arm64/boot/dts/freescale/
X: arch/arm64/boot/dts/freescale/fsl-*
X: arch/arm64/boot/dts/freescale/qoriq-*
X: drivers/media/i2c/
F: drivers/*/*wpcm*
ARM/NXP S32G ARCHITECTURE
- M: Chester Lin <clin@suse.com>
+ M: Chester Lin <chester62515@gmail.com>
S: Supported
B: https://github.com/ClangBuiltLinux/linux/issues
CLANG/LLVM BUILD SUPPORT
S: Supported
W: https://clangbuiltlinux.github.io/
COMPILER ATTRIBUTES
S: Maintained
F: include/linux/compiler_attributes.h
F: drivers/media/pci/cx88/
CXD2820R MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/cxd2820r*
CXGB3 ETHERNET DRIVER (CXGB3)
F: drivers/input/keyboard/cypress-sf.c
CYPRESS_FIRMWARE MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/common/cypress_firmware*
CYTTSP TOUCHSCREEN DRIVER
F: drivers/media/pci/dt3155/
DVB_USB_AF9015 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/af9015*
DVB_USB_AF9035 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/af9035*
DVB_USB_ANYSEE MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/anysee*
DVB_USB_AU6610 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/au6610*
DVB_USB_CE6230 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/ce6230*
DVB_USB_CXUSB MEDIA DRIVER
F: drivers/media/usb/dvb-usb/cxusb*
DVB_USB_EC168 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/ec168*
DVB_USB_GL861 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/gl861*
DVB_USB_MXL111SF MEDIA DRIVER
F: drivers/media/usb/dvb-usb-v2/mxl111sf*
DVB_USB_RTL28XXU MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/rtl28xxu*
DVB_USB_V2 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/dvb-usb-v2/dvb_usb*
F: drivers/media/usb/dvb-usb-v2/usb_urb.c
F: drivers/input/misc/e3x0-button.c
E4000 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/e4000*
EARTH_PT1 MEDIA DRIVER
F: drivers/media/pci/pt3/
EC100 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/ec100*
ECRYPT FILE SYSTEM
S: Maintained
+ W: https://erofs.docs.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
F: Documentation/ABI/testing/sysfs-fs-erofs
F: Documentation/filesystems/erofs.rst
F: drivers/media/tuners/fc0011.h
FC2580 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/fc2580*
FCOE SUBSYSTEM (libfc, libfcoe, fcoe)
F: include/uapi/drm/habanalabs_accel.h
HACKRF MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/hackrf/
HANDSHAKE UPCALL FOR TRANSPORT LAYER SECURITY
F: include/linux/hisi_acc_qm.h
HISILICON ROCE DRIVER
S: Maintained
INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER
S: Maintained
W: https://slimbootloader.github.io/security/firmware-update.html
F: drivers/platform/x86/intel/wmi/sbl-fw-update.c
F: drivers/hwmon/it87.c
IT913X MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/it913x*
ITE IT66121 HDMI BRIDGE DRIVER
KERNEL BUILD + files below scripts/ (unless maintained elsewhere)
S: Maintained
F: include/uapi/linux/ndctl.h
F: tools/testing/nvdimm/
+ LIBRARY CODE
+ S: Supported
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-nonmm-unstable
+ F: lib/*
+
LICENSES and SPDX stuff
F: arch/m68k/hp300/
M88DS3103 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/m88ds3103*
M88RS2000 MEDIA DRIVER
MELLANOX HARDWARE PLATFORM SUPPORT
S: Supported
MICROSOFT SURFACE HARDWARE PLATFORM SUPPORT
S: Maintained
F: mm/mmu_gather.c
MN88472 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/mn88472*
MN88473 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/mn88473*
F: drivers/platform/x86/msi-wmi.c
MSI001 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/msi001*
MSI2500 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/usb/msi2500/
MSTAR INTERRUPT CONTROLLER DRIVER
S: Maintained
+ P: Documentation/process/maintainer-netdev.rst
Q: https://patchwork.kernel.org/project/netdevbpf/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
S: Maintained
+ P: Documentation/process/maintainer-netdev.rst
Q: https://patchwork.kernel.org/project/netdevbpf/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
F: Documentation/process/maintainer-netdev.rst
F: Documentation/userspace-api/netlink/
F: include/linux/in.h
+ F: include/linux/indirect_call_wrapper.h
F: include/linux/net.h
F: include/linux/netdevice.h
F: include/net/
F: net/
F: tools/net/
F: tools/testing/selftests/net/
+ X: net/9p/
X: net/bluetooth/
NETWORKING [IPSEC]
F: include/uapi/linux/fsl_mc.h
QT1010 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/qt1010*
QUALCOMM ATH12K WIRELESS DRIVER
S: Maintained
F: drivers/iommu/arm/arm-smmu/qcom_iommu.c
+ F: drivers/iommu/arm/arm-smmu/arm-smmu-qcom*
+ F: drivers/iommu/msm_iommu*
QUALCOMM IPC ROUTER (QRTR) DRIVER
F: drivers/tty/rpmsg_tty.c
RTL2830 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/rtl2830*
RTL2832 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/rtl2832*
RTL2832_SDR MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/rtl2832_sdr*
RTL8180 WIRELESS DRIVER
F: include/media/drv-intf/sh_vou.h
SI2157 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/si2157*
SI2165 MEDIA DRIVER
F: drivers/media/dvb-frontends/si2165*
SI2168 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/si2168*
SI470X FM RADIO RECEIVER I2C DRIVER
F: net/ipv4/tcp_lp.c
TDA10071 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/dvb-frontends/tda10071*
TDA18212 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/tda18212*
TDA18218 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/tda18218*
TDA18250 MEDIA DRIVER
TRACING
S: Maintained
F: include/uapi/linux/tty.h
TUA9001 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org
- W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
- T: git git://linuxtv.org/anttip/media_tree.git
F: drivers/media/tuners/tua9001*
TULIP NETWORK DRIVERS
S: Maintained
F: drivers/char/virtio_console.c
-F: include/linux/virtio_console.h
F: include/uapi/linux/virtio_console.h
VIRTIO CORE AND NET DRIVERS
X86 PLATFORM DRIVERS
S: Maintained
Q: https://patchwork.kernel.org/project/platform-driver-x86/list/
F: drivers/net/wireless/zydas/zd1211rw/
ZD1301 MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org/
- W: http://palosaari.fi/linux/
Q: https://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/usb/dvb-usb-v2/zd1301*
ZD1301_DEMOD MEDIA DRIVER
- S: Maintained
+ S: Orphan
W: https://linuxtv.org/
- W: http://palosaari.fi/linux/
Q: https://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/zd1301_demod*
/* -- Glue layer (serdev_device -> ssam_controller). ------------------------ */
-static int ssam_receive_buf(struct serdev_device *dev, const unsigned char *buf,
- size_t n)
+static ssize_t ssam_receive_buf(struct serdev_device *dev, const u8 *buf,
+ size_t n)
{
struct ssam_controller *ctrl;
+ int ret;
ctrl = serdev_device_get_drvdata(dev);
- return ssam_controller_receive_buf(ctrl, buf, n);
+ ret = ssam_controller_receive_buf(ctrl, buf, n);
+
+ return ret < 0 ? 0 : ret;
}
static void ssam_write_wakeup(struct serdev_device *dev)
return 0;
}
-static int dw8250_remove(struct platform_device *pdev)
+static void dw8250_remove(struct platform_device *pdev)
{
struct dw8250_data *data = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
-
- return 0;
}
static int dw8250_suspend(struct device *dev)
{ "INT33C5", (kernel_ulong_t)&dw8250_dw_apb },
{ "INT3434", (kernel_ulong_t)&dw8250_dw_apb },
{ "INT3435", (kernel_ulong_t)&dw8250_dw_apb },
+ { "INTC10EE", (kernel_ulong_t)&dw8250_dw_apb },
{ },
};
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
.acpi_match_table = dw8250_acpi_match,
},
.probe = dw8250_probe,
- .remove = dw8250_remove,
+ .remove_new = dw8250_remove,
};
module_platform_driver(dw8250_platform_driver);
if (priv->habit & UART_HAS_RHR_IT_DIS) {
reg = serial_in(p, UART_OMAP_IER2);
reg &= ~UART_OMAP_IER2_RHR_IT_DIS;
- serial_out(p, UART_OMAP_IER2, UART_OMAP_IER2_RHR_IT_DIS);
+ serial_out(p, UART_OMAP_IER2, reg);
}
dmaengine_tx_status(rxchan, cookie, &state);
if (priv->habit & UART_HAS_RHR_IT_DIS) {
reg = serial_in(p, UART_OMAP_IER2);
reg |= UART_OMAP_IER2_RHR_IT_DIS;
- serial_out(p, UART_OMAP_IER2, UART_OMAP_IER2_RHR_IT_DIS);
+ serial_out(p, UART_OMAP_IER2, reg);
}
dma_async_issue_pending(dma->rxchan);
status = serial_port_in(port, UART_LSR);
- if (priv->habit & UART_HAS_EFR2)
- am654_8250_handle_rx_dma(up, iir, status);
- else
- status = omap_8250_handle_rx_dma(up, iir, status);
+ if ((iir & 0x3f) != UART_IIR_THRI) {
+ if (priv->habit & UART_HAS_EFR2)
+ am654_8250_handle_rx_dma(up, iir, status);
+ else
+ status = omap_8250_handle_rx_dma(up, iir, status);
+ }
serial8250_modem_status(up);
if (status & UART_LSR_THRE && up->dma->tx_err) {
return ret;
}
-static int omap8250_remove(struct platform_device *pdev)
+static void omap8250_remove(struct platform_device *pdev)
{
struct omap8250_priv *priv = platform_get_drvdata(pdev);
struct uart_8250_port *up;
err = pm_runtime_resume_and_get(&pdev->dev);
if (err)
- return err;
+ dev_err(&pdev->dev, "Failed to resume hardware\n");
up = serial8250_get_port(priv->line);
omap_8250_shutdown(&up->port);
pm_runtime_disable(&pdev->dev);
cpu_latency_qos_remove_request(&priv->pm_qos_request);
device_init_wakeup(&pdev->dev, false);
- return 0;
}
static int omap8250_prepare(struct device *dev)
.of_match_table = omap8250_dt_ids,
},
.probe = omap8250_probe,
- .remove = omap8250_remove,
+ .remove_new = omap8250_remove,
};
module_platform_driver(omap8250_platform_driver);
/* Deals with DMA transactions */
- struct pl011_sgbuf {
- struct scatterlist sg;
- char *buf;
+ struct pl011_dmabuf {
+ dma_addr_t dma;
+ size_t len;
+ char *buf;
};
struct pl011_dmarx_data {
struct dma_chan *chan;
struct completion complete;
bool use_buf_b;
- struct pl011_sgbuf sgbuf_a;
- struct pl011_sgbuf sgbuf_b;
+ struct pl011_dmabuf dbuf_a;
+ struct pl011_dmabuf dbuf_b;
dma_cookie_t cookie;
bool running;
struct timer_list timer;
struct pl011_dmatx_data {
struct dma_chan *chan;
- struct scatterlist sg;
+ dma_addr_t dma;
+ size_t len;
char *buf;
bool queued;
};
#define PL011_DMA_BUFFER_SIZE PAGE_SIZE
- static int pl011_sgbuf_init(struct dma_chan *chan, struct pl011_sgbuf *sg,
+ static int pl011_dmabuf_init(struct dma_chan *chan, struct pl011_dmabuf *db,
enum dma_data_direction dir)
{
- dma_addr_t dma_addr;
-
- sg->buf = dma_alloc_coherent(chan->device->dev,
- PL011_DMA_BUFFER_SIZE, &dma_addr, GFP_KERNEL);
- if (!sg->buf)
+ db->buf = dma_alloc_coherent(chan->device->dev, PL011_DMA_BUFFER_SIZE,
+ &db->dma, GFP_KERNEL);
+ if (!db->buf)
return -ENOMEM;
-
- sg_init_table(&sg->sg, 1);
- sg_set_page(&sg->sg, phys_to_page(dma_addr),
- PL011_DMA_BUFFER_SIZE, offset_in_page(dma_addr));
- sg_dma_address(&sg->sg) = dma_addr;
- sg_dma_len(&sg->sg) = PL011_DMA_BUFFER_SIZE;
+ db->len = PL011_DMA_BUFFER_SIZE;
return 0;
}
- static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
+ static void pl011_dmabuf_free(struct dma_chan *chan, struct pl011_dmabuf *db,
enum dma_data_direction dir)
{
- if (sg->buf) {
+ if (db->buf) {
dma_free_coherent(chan->device->dev,
- PL011_DMA_BUFFER_SIZE, sg->buf,
- sg_dma_address(&sg->sg));
+ PL011_DMA_BUFFER_SIZE, db->buf, db->dma);
}
}
dma_chan_name(uap->dmatx.chan));
/* Optionally make use of an RX channel as well */
- chan = dma_request_slave_channel(dev, "rx");
+ chan = dma_request_chan(dev, "rx");
- if (!chan && plat && plat->dma_rx_param) {
+ if (IS_ERR(chan) && plat && plat->dma_rx_param) {
chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
if (!chan) {
}
}
- if (chan) {
+ if (!IS_ERR(chan)) {
struct dma_slave_config rx_conf = {
.src_addr = uap->port.mapbase +
pl011_reg_to_offset(uap, REG_DR),
uart_port_lock_irqsave(&uap->port, &flags);
if (uap->dmatx.queued)
- dma_unmap_sg(dmatx->chan->device->dev, &dmatx->sg, 1,
- DMA_TO_DEVICE);
+ dma_unmap_single(dmatx->chan->device->dev, dmatx->dma,
+ dmatx->len, DMA_TO_DEVICE);
dmacr = uap->dmacr;
uap->dmacr = dmacr & ~UART011_TXDMAE;
memcpy(&dmatx->buf[first], &xmit->buf[0], second);
}
- dmatx->sg.length = count;
-
- if (dma_map_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE) != 1) {
+ dmatx->len = count;
+ dmatx->dma = dma_map_single(dma_dev->dev, dmatx->buf, count,
+ DMA_TO_DEVICE);
+ if (dmatx->dma == DMA_MAPPING_ERROR) {
uap->dmatx.queued = false;
dev_dbg(uap->port.dev, "unable to map TX DMA\n");
return -EBUSY;
}
- desc = dmaengine_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV,
+ desc = dmaengine_prep_slave_single(chan, dmatx->dma, dmatx->len, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
- dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE);
+ dma_unmap_single(dma_dev->dev, dmatx->dma, dmatx->len, DMA_TO_DEVICE);
uap->dmatx.queued = false;
/*
* If DMA cannot be used right now, we complete this
dmaengine_terminate_async(uap->dmatx.chan);
if (uap->dmatx.queued) {
- dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
- DMA_TO_DEVICE);
+ dma_unmap_single(uap->dmatx.chan->device->dev, uap->dmatx.dma,
+ uap->dmatx.len, DMA_TO_DEVICE);
uap->dmatx.queued = false;
uap->dmacr &= ~UART011_TXDMAE;
pl011_write(uap->dmacr, uap, REG_DMACR);
struct dma_chan *rxchan = uap->dmarx.chan;
struct pl011_dmarx_data *dmarx = &uap->dmarx;
struct dma_async_tx_descriptor *desc;
- struct pl011_sgbuf *sgbuf;
+ struct pl011_dmabuf *dbuf;
if (!rxchan)
return -EIO;
/* Start the RX DMA job */
- sgbuf = uap->dmarx.use_buf_b ?
- &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
- desc = dmaengine_prep_slave_sg(rxchan, &sgbuf->sg, 1,
+ dbuf = uap->dmarx.use_buf_b ?
+ &uap->dmarx.dbuf_b : &uap->dmarx.dbuf_a;
+ desc = dmaengine_prep_slave_single(rxchan, dbuf->dma, dbuf->len,
DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
/*
bool readfifo)
{
struct tty_port *port = &uap->port.state->port;
- struct pl011_sgbuf *sgbuf = use_buf_b ?
- &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
+ struct pl011_dmabuf *dbuf = use_buf_b ?
+ &uap->dmarx.dbuf_b : &uap->dmarx.dbuf_a;
int dma_count = 0;
u32 fifotaken = 0; /* only used for vdbg() */
if (uap->dmarx.poll_rate) {
/* The data can be taken by polling */
- dmataken = sgbuf->sg.length - dmarx->last_residue;
+ dmataken = dbuf->len - dmarx->last_residue;
/* Recalculate the pending size */
if (pending >= dmataken)
pending -= dmataken;
* Note that tty_insert_flip_buf() tries to take as many chars
* as it can.
*/
- dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken,
+ dma_count = tty_insert_flip_string(port, dbuf->buf + dmataken,
pending);
uap->port.icount.rx += dma_count;
/* Reset the last_residue for Rx DMA poll */
if (uap->dmarx.poll_rate)
- dmarx->last_residue = sgbuf->sg.length;
+ dmarx->last_residue = dbuf->len;
/*
* Only continue with trying to read the FIFO if all DMA chars have
{
struct pl011_dmarx_data *dmarx = &uap->dmarx;
struct dma_chan *rxchan = dmarx->chan;
- struct pl011_sgbuf *sgbuf = dmarx->use_buf_b ?
- &dmarx->sgbuf_b : &dmarx->sgbuf_a;
+ struct pl011_dmabuf *dbuf = dmarx->use_buf_b ?
+ &dmarx->dbuf_b : &dmarx->dbuf_a;
size_t pending;
struct dma_tx_state state;
enum dma_status dmastat;
pl011_write(uap->dmacr, uap, REG_DMACR);
uap->dmarx.running = false;
- pending = sgbuf->sg.length - state.residue;
+ pending = dbuf->len - state.residue;
BUG_ON(pending > PL011_DMA_BUFFER_SIZE);
/* Then we terminate the transfer - we now know our residue */
dmaengine_terminate_all(rxchan);
struct pl011_dmarx_data *dmarx = &uap->dmarx;
struct dma_chan *rxchan = dmarx->chan;
bool lastbuf = dmarx->use_buf_b;
- struct pl011_sgbuf *sgbuf = dmarx->use_buf_b ?
- &dmarx->sgbuf_b : &dmarx->sgbuf_a;
+ struct pl011_dmabuf *dbuf = dmarx->use_buf_b ?
+ &dmarx->dbuf_b : &dmarx->dbuf_a;
size_t pending;
struct dma_tx_state state;
int ret;
* the DMA irq handler. So we check the residue here.
*/
rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
- pending = sgbuf->sg.length - state.residue;
+ pending = dbuf->len - state.residue;
BUG_ON(pending > PL011_DMA_BUFFER_SIZE);
/* Then we terminate the transfer - we now know our residue */
dmaengine_terminate_all(rxchan);
unsigned long flags;
unsigned int dmataken = 0;
unsigned int size = 0;
- struct pl011_sgbuf *sgbuf;
+ struct pl011_dmabuf *dbuf;
int dma_count;
struct dma_tx_state state;
- sgbuf = dmarx->use_buf_b ? &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
+ dbuf = dmarx->use_buf_b ? &uap->dmarx.dbuf_b : &uap->dmarx.dbuf_a;
rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
if (likely(state.residue < dmarx->last_residue)) {
- dmataken = sgbuf->sg.length - dmarx->last_residue;
+ dmataken = dbuf->len - dmarx->last_residue;
size = dmarx->last_residue - state.residue;
- dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken,
+ dma_count = tty_insert_flip_string(port, dbuf->buf + dmataken,
size);
if (dma_count == size)
dmarx->last_residue = state.residue;
return;
}
- sg_init_one(&uap->dmatx.sg, uap->dmatx.buf, PL011_DMA_BUFFER_SIZE);
+ uap->dmatx.len = PL011_DMA_BUFFER_SIZE;
/* The DMA buffer is now the FIFO the TTY subsystem can use */
uap->port.fifosize = PL011_DMA_BUFFER_SIZE;
goto skip_rx;
/* Allocate and map DMA RX buffers */
- ret = pl011_sgbuf_init(uap->dmarx.chan, &uap->dmarx.sgbuf_a,
+ ret = pl011_dmabuf_init(uap->dmarx.chan, &uap->dmarx.dbuf_a,
DMA_FROM_DEVICE);
if (ret) {
dev_err(uap->port.dev, "failed to init DMA %s: %d\n",
goto skip_rx;
}
- ret = pl011_sgbuf_init(uap->dmarx.chan, &uap->dmarx.sgbuf_b,
+ ret = pl011_dmabuf_init(uap->dmarx.chan, &uap->dmarx.dbuf_b,
DMA_FROM_DEVICE);
if (ret) {
dev_err(uap->port.dev, "failed to init DMA %s: %d\n",
"RX buffer B", ret);
- pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a,
+ pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_a,
DMA_FROM_DEVICE);
goto skip_rx;
}
/* In theory, this should already be done by pl011_dma_flush_buffer */
dmaengine_terminate_all(uap->dmatx.chan);
if (uap->dmatx.queued) {
- dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
- DMA_TO_DEVICE);
+ dma_unmap_single(uap->dmatx.chan->device->dev,
+ uap->dmatx.dma, uap->dmatx.len,
+ DMA_TO_DEVICE);
uap->dmatx.queued = false;
}
if (uap->using_rx_dma) {
dmaengine_terminate_all(uap->dmarx.chan);
/* Clean up the RX DMA */
- pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a, DMA_FROM_DEVICE);
- pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_b, DMA_FROM_DEVICE);
+ pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_a, DMA_FROM_DEVICE);
+ pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_b, DMA_FROM_DEVICE);
if (uap->dmarx.poll_rate)
del_timer_sync(&uap->dmarx.timer);
uap->using_rx_dma = false;
return pl011_register_port(uap);
}
-static int sbsa_uart_remove(struct platform_device *pdev)
+static void sbsa_uart_remove(struct platform_device *pdev)
{
struct uart_amba_port *uap = platform_get_drvdata(pdev);
uart_remove_one_port(&amba_reg, &uap->port);
pl011_unregister_port(uap);
- return 0;
}
static const struct of_device_id sbsa_uart_of_match[] = {
static struct platform_driver arm_sbsa_uart_platform_driver = {
.probe = sbsa_uart_probe,
- .remove = sbsa_uart_remove,
+ .remove_new = sbsa_uart_remove,
.driver = {
.name = "sbsa-uart",
.pm = &pl011_dev_pm_ops,
*/
static void ma35d1serial_console_write(struct console *co, const char *s, u32 count)
{
- struct uart_ma35d1_port *up = &ma35d1serial_ports[co->index];
+ struct uart_ma35d1_port *up;
unsigned long flags;
int locked = 1;
u32 ier;
+ if ((co->index < 0) || (co->index >= MA35_UART_NR)) {
+ pr_warn("Failed to write on ononsole port %x, out of range\n",
+ co->index);
+ return;
+ }
+
+ up = &ma35d1serial_ports[co->index];
+
if (up->port.sysrq)
locked = 0;
else if (oops_in_progress)
/*
* Remove serial ports registered against a platform device.
*/
-static int ma35d1serial_remove(struct platform_device *dev)
+static void ma35d1serial_remove(struct platform_device *dev)
{
struct uart_port *port = platform_get_drvdata(dev);
struct uart_ma35d1_port *up = to_ma35d1_uart_port(port);
uart_remove_one_port(&ma35d1serial_reg, port);
clk_disable_unprepare(up->clk);
- return 0;
}
static int ma35d1serial_suspend(struct platform_device *dev, pm_message_t state)
static struct platform_driver ma35d1serial_driver = {
.probe = ma35d1serial_probe,
- .remove = ma35d1serial_remove,
+ .remove_new = ma35d1serial_remove,
.suspend = ma35d1serial_suspend,
.resume = ma35d1serial_resume,
.driver = {
/* Misc definitions */
+#define SC16IS7XX_SPI_READ_BIT BIT(7)
#define SC16IS7XX_FIFO_SIZE (64)
-#define SC16IS7XX_REG_SHIFT 2
#define SC16IS7XX_GPIOS_PER_BANK 4
struct sc16is7xx_devtype {
struct sc16is7xx_one {
struct uart_port port;
u8 line;
+ struct regmap *regmap;
struct kthread_work tx_work;
struct kthread_work reg_work;
struct kthread_delayed_work ms_work;
#define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e)))
-static int sc16is7xx_line(struct uart_port *port)
-{
- struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
-
- return one->line;
-}
-
static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
{
- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
unsigned int val = 0;
- const u8 line = sc16is7xx_line(port);
- regmap_read(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, &val);
+ regmap_read(one->regmap, reg, &val);
return val;
}
static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val)
{
- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
- const u8 line = sc16is7xx_line(port);
+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
- regmap_write(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, val);
+ regmap_write(one->regmap, reg, val);
}
static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
- const u8 line = sc16is7xx_line(port);
- u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | line;
+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
- regcache_cache_bypass(s->regmap, true);
- regmap_raw_read(s->regmap, addr, s->buf, rxlen);
- regcache_cache_bypass(s->regmap, false);
+ regcache_cache_bypass(one->regmap, true);
+ regmap_raw_read(one->regmap, SC16IS7XX_RHR_REG, s->buf, rxlen);
+ regcache_cache_bypass(one->regmap, false);
}
static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
- const u8 line = sc16is7xx_line(port);
- u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line;
+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
/*
* Don't send zero-length data, at least on SPI it confuses the chip
if (unlikely(!to_send))
return;
- regcache_cache_bypass(s->regmap, true);
- regmap_raw_write(s->regmap, addr, s->buf, to_send);
- regcache_cache_bypass(s->regmap, false);
+ regcache_cache_bypass(one->regmap, true);
+ regmap_raw_write(one->regmap, SC16IS7XX_THR_REG, s->buf, to_send);
+ regcache_cache_bypass(one->regmap, false);
}
static void sc16is7xx_port_update(struct uart_port *port, u8 reg,
u8 mask, u8 val)
{
- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
- const u8 line = sc16is7xx_line(port);
+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
- regmap_update_bits(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line,
- mask, val);
+ regmap_update_bits(one->regmap, reg, mask, val);
}
static int sc16is7xx_alloc_line(void)
static bool sc16is7xx_regmap_volatile(struct device *dev, unsigned int reg)
{
- switch (reg >> SC16IS7XX_REG_SHIFT) {
+ switch (reg) {
case SC16IS7XX_RHR_REG:
case SC16IS7XX_IIR_REG:
case SC16IS7XX_LSR_REG:
static bool sc16is7xx_regmap_precious(struct device *dev, unsigned int reg)
{
- switch (reg >> SC16IS7XX_REG_SHIFT) {
+ switch (reg) {
case SC16IS7XX_RHR_REG:
return true;
default:
static int sc16is7xx_set_baud(struct uart_port *port, int baud)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
u8 lcr;
u8 prescaler = 0;
unsigned long clk = port->uartclk, div = clk / 16 / baud;
SC16IS7XX_LCR_CONF_MODE_B);
/* Enable enhanced features */
- regcache_cache_bypass(s->regmap, true);
+ regcache_cache_bypass(one->regmap, true);
sc16is7xx_port_update(port, SC16IS7XX_EFR_REG,
SC16IS7XX_EFR_ENABLE_BIT,
SC16IS7XX_EFR_ENABLE_BIT);
- regcache_cache_bypass(s->regmap, false);
+ regcache_cache_bypass(one->regmap, false);
/* Put LCR back to the normal mode */
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
SC16IS7XX_LCR_CONF_MODE_A);
/* Write the new divisor */
- regcache_cache_bypass(s->regmap, true);
+ regcache_cache_bypass(one->regmap, true);
sc16is7xx_port_write(port, SC16IS7XX_DLH_REG, div / 256);
sc16is7xx_port_write(port, SC16IS7XX_DLL_REG, div % 256);
- regcache_cache_bypass(s->regmap, false);
+ regcache_cache_bypass(one->regmap, false);
/* Put LCR back to the normal mode */
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
/* Get length of data pending in circular buffer */
to_send = uart_circ_chars_pending(xmit);
if (likely(to_send)) {
- /* Limit to size of TX FIFO */
+ /* Limit to space available in TX FIFO */
txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG);
if (txlen > SC16IS7XX_FIFO_SIZE) {
dev_err_ratelimited(port->dev,
case SC16IS7XX_IIR_RTOI_SRC:
case SC16IS7XX_IIR_XOFFI_SRC:
rxlen = sc16is7xx_port_read(port, SC16IS7XX_RXLVL_REG);
+
+ /*
+ * There is a silicon bug that makes the chip report a
+ * time-out interrupt but no data in the FIFO. This is
+ * described in errata section 18.1.4.
+ *
+ * When this happens, read one byte from the FIFO to
+ * clear the interrupt.
+ */
+ if (iir == SC16IS7XX_IIR_RTOI_SRC && !rxlen)
+ rxlen = 1;
+
if (rxlen)
sc16is7xx_handle_rx(port, rxlen, iir);
break;
SC16IS7XX_LCR_CONF_MODE_B);
/* Configure flow control */
- regcache_cache_bypass(s->regmap, true);
+ regcache_cache_bypass(one->regmap, true);
sc16is7xx_port_write(port, SC16IS7XX_XON1_REG, termios->c_cc[VSTART]);
sc16is7xx_port_write(port, SC16IS7XX_XOFF1_REG, termios->c_cc[VSTOP]);
SC16IS7XX_EFR_REG,
SC16IS7XX_EFR_FLOWCTRL_BITS,
flow);
- regcache_cache_bypass(s->regmap, false);
+ regcache_cache_bypass(one->regmap, false);
/* Update LCR register */
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
static int sc16is7xx_startup(struct uart_port *port)
{
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
unsigned int val;
unsigned long flags;
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
SC16IS7XX_LCR_CONF_MODE_B);
- regcache_cache_bypass(s->regmap, true);
+ regcache_cache_bypass(one->regmap, true);
/* Enable write access to enhanced features and internal clock div */
sc16is7xx_port_update(port, SC16IS7XX_EFR_REG,
SC16IS7XX_TCR_RX_RESUME(24) |
SC16IS7XX_TCR_RX_HALT(48));
- regcache_cache_bypass(s->regmap, false);
+ regcache_cache_bypass(one->regmap, false);
/* Now, initialize the UART */
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8);
if (s->mctrl_mask)
regmap_update_bits(
s->regmap,
- SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT,
+ SC16IS7XX_IOCONTROL_REG,
SC16IS7XX_IOCONTROL_MODEM_A_BIT |
SC16IS7XX_IOCONTROL_MODEM_B_BIT, s->mctrl_mask);
static int sc16is7xx_probe(struct device *dev,
const struct sc16is7xx_devtype *devtype,
- struct regmap *regmap, int irq)
+ struct regmap *regmaps[], int irq)
{
unsigned long freq = 0, *pfreq = dev_get_platdata(dev);
unsigned int val;
int i, ret;
struct sc16is7xx_port *s;
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
+ for (i = 0; i < devtype->nr_uart; i++)
+ if (IS_ERR(regmaps[i]))
+ return PTR_ERR(regmaps[i]);
/*
* This device does not have an identification register that would
* tell us if we are really connected to the correct device.
* The best we can do is to check if communication is at all possible.
*/
- ret = regmap_read(regmap,
- SC16IS7XX_LSR_REG << SC16IS7XX_REG_SHIFT, &val);
+ ret = regmap_read(regmaps[0], SC16IS7XX_LSR_REG, &val);
if (ret < 0)
return -EPROBE_DEFER;
return -EINVAL;
}
- s->regmap = regmap;
+ s->regmap = regmaps[0];
s->devtype = devtype;
dev_set_drvdata(dev, s);
mutex_init(&s->efr_lock);
sched_set_fifo(s->kworker_task);
/* reset device, purging any pending irq / data */
- regmap_write(s->regmap, SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT,
- SC16IS7XX_IOCONTROL_SRESET_BIT);
+ regmap_write(s->regmap, SC16IS7XX_IOCONTROL_REG,
+ SC16IS7XX_IOCONTROL_SRESET_BIT);
for (i = 0; i < devtype->nr_uart; ++i) {
s->p[i].line = i;
s->p[i].port.ops = &sc16is7xx_ops;
s->p[i].old_mctrl = 0;
s->p[i].port.line = sc16is7xx_alloc_line();
+ s->p[i].regmap = regmaps[i];
if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) {
ret = -ENOMEM;
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG,
SC16IS7XX_LCR_CONF_MODE_B);
- regcache_cache_bypass(s->regmap, true);
+ regcache_cache_bypass(regmaps[i], true);
/* Enable write access to enhanced features */
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFR_REG,
SC16IS7XX_EFR_ENABLE_BIT);
- regcache_cache_bypass(s->regmap, false);
+ regcache_cache_bypass(regmaps[i], false);
/* Restore access to general registers */
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG, 0x00);
MODULE_DEVICE_TABLE(of, sc16is7xx_dt_ids);
static struct regmap_config regcfg = {
- .reg_bits = 7,
- .pad_bits = 1,
+ .reg_bits = 5,
+ .pad_bits = 3,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.volatile_reg = sc16is7xx_regmap_volatile,
.precious_reg = sc16is7xx_regmap_precious,
+ .max_register = SC16IS7XX_EFCR_REG,
};
+static const char *sc16is7xx_regmap_name(unsigned int port_id)
+{
+ static char buf[6];
+
+ snprintf(buf, sizeof(buf), "port%d", port_id);
+
+ return buf;
+}
+
+static unsigned int sc16is7xx_regmap_port_mask(unsigned int port_id)
+{
+ /* CH1,CH0 are at bits 2:1. */
+ return port_id << 1;
+}
+
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
static int sc16is7xx_spi_probe(struct spi_device *spi)
{
const struct sc16is7xx_devtype *devtype;
- struct regmap *regmap;
+ struct regmap *regmaps[2];
+ unsigned int i;
int ret;
/* Setup SPI bus */
devtype = (struct sc16is7xx_devtype *)id_entry->driver_data;
}
- regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) |
- (devtype->nr_uart - 1);
- regmap = devm_regmap_init_spi(spi, ®cfg);
+ for (i = 0; i < devtype->nr_uart; i++) {
+ regcfg.name = sc16is7xx_regmap_name(i);
+ /*
+ * If read_flag_mask is 0, the regmap code sets it to a default
+ * of 0x80. Since we specify our own mask, we must add the READ
+ * bit ourselves:
+ */
+ regcfg.read_flag_mask = sc16is7xx_regmap_port_mask(i) |
+ SC16IS7XX_SPI_READ_BIT;
+ regcfg.write_flag_mask = sc16is7xx_regmap_port_mask(i);
+ regmaps[i] = devm_regmap_init_spi(spi, ®cfg);
+ }
- return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq);
+ return sc16is7xx_probe(&spi->dev, devtype, regmaps, spi->irq);
}
static void sc16is7xx_spi_remove(struct spi_device *spi)
{
const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
const struct sc16is7xx_devtype *devtype;
- struct regmap *regmap;
+ struct regmap *regmaps[2];
+ unsigned int i;
if (i2c->dev.of_node) {
devtype = device_get_match_data(&i2c->dev);
devtype = (struct sc16is7xx_devtype *)id->driver_data;
}
- regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) |
- (devtype->nr_uart - 1);
- regmap = devm_regmap_init_i2c(i2c, ®cfg);
+ for (i = 0; i < devtype->nr_uart; i++) {
+ regcfg.name = sc16is7xx_regmap_name(i);
+ regcfg.read_flag_mask = sc16is7xx_regmap_port_mask(i);
+ regcfg.write_flag_mask = sc16is7xx_regmap_port_mask(i);
+ regmaps[i] = devm_regmap_init_i2c(i2c, ®cfg);
+ }
- return sc16is7xx_probe(&i2c->dev, devtype, regmap, i2c->irq);
+ return sc16is7xx_probe(&i2c->dev, devtype, regmaps, i2c->irq);
}
static void sc16is7xx_i2c_remove(struct i2c_client *client)