summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-10-22 19:31:08 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-10-22 19:31:08 -0300
commit670027c507e99521d416994a18a498def9ef2ea3 (patch)
tree74b4d761a9e7904a4f8aa4b58b2dc9801f22284d /drivers
parentd0b2f91bede3bd5e3d24dd6803e56eee959c1797 (diff)
Linux-libre 4.8.3-gnupck-4.8.3-gnu
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/int340x_thermal.c53
-rw-r--r--drivers/acpi/nfit.c2714
-rw-r--r--drivers/acpi/nfit.h223
-rw-r--r--drivers/ata/ahci_brcmstb.c380
-rw-r--r--drivers/block/zram/zcomp_lz4.c56
-rw-r--r--drivers/block/zram/zcomp_lz4.h17
-rw-r--r--drivers/block/zram/zcomp_lzo.c56
-rw-r--r--drivers/block/zram/zcomp_lzo.h17
-rw-r--r--drivers/char/genrtc.c539
-rw-r--r--drivers/clk/meson/clkc.c249
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c2
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c2
-rw-r--r--drivers/crypto/qat/qat_common/qat_rsaprivkey.asn111
-rw-r--r--drivers/crypto/qat/qat_common/qat_rsapubkey.asn14
-rw-r--r--drivers/dma/xilinx/xilinx_vdma.c2310
-rw-r--r--drivers/gpu/drm/amd/amdgpu/iceland_smumgr.h41
-rw-r--r--drivers/gpu/drm/i2c/adv7511.c1024
-rw-r--r--drivers/gpu/drm/i2c/adv7511.h289
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c1587
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c117
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmicon.h31
-rw-r--r--drivers/hid/hid-thingm.c263
-rw-r--r--drivers/hsi/hsi.c781
-rw-r--r--drivers/iio/pressure/bmp280.c922
-rw-r--r--drivers/infiniband/hw/hfi1/twsi.c489
-rw-r--r--drivers/infiniband/hw/hfi1/twsi.h65
-rw-r--r--drivers/iommu/msm_iommu_dev.c381
-rw-r--r--drivers/leds/trigger/ledtrig-ide-disk.c36
-rw-r--r--drivers/misc/bh1780gli.c259
-rw-r--r--drivers/misc/lkdtm.c1023
-rw-r--r--drivers/mmc/host/sdhci-bcm2835.c204
-rw-r--r--drivers/net/can/rcar_can.c929
-rw-r--r--drivers/net/dsa/mv88e6xxx.c3723
-rw-r--r--drivers/net/dsa/mv88e6xxx.h624
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_ppm.c464
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_ppm.h310
-rw-r--r--drivers/net/wireless/broadcom/b43/phy_a.c595
-rw-r--r--drivers/pci/ecam.h67
-rw-r--r--drivers/pwm/pwm-tipwmss.h39
-rw-r--r--drivers/scsi/hosts.c12
-rw-r--r--drivers/scsi/ibmvscsi/viosrp.h225
-rw-r--r--drivers/soc/brcmstb/Kconfig10
-rw-r--r--drivers/soc/brcmstb/Makefile1
-rw-r--r--drivers/soc/brcmstb/biuctrl.c116
-rw-r--r--drivers/soc/brcmstb/common.c99
-rw-r--r--drivers/spi/spi-octeon.c255
-rw-r--r--drivers/staging/android/sw_sync.h59
-rw-r--r--drivers/staging/android/sync.c221
-rw-r--r--drivers/staging/android/sync.h154
-rw-r--r--drivers/staging/android/uapi/sw_sync.h32
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c187
-rw-r--r--drivers/staging/iio/accel/lis3l02dq.h217
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c814
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c428
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_rmtacl.c299
-rw-r--r--drivers/staging/lustre/lustre/llite/lloop.c883
-rw-r--r--drivers/staging/lustre/lustre/llite/remote_perm.c324
-rw-r--r--drivers/staging/lustre/lustre/obdclass/acl.c415
-rw-r--r--drivers/staging/media/mn88472/Kconfig7
-rw-r--r--drivers/staging/media/mn88472/Makefile5
-rw-r--r--drivers/staging/media/mn88472/TODO21
-rw-r--r--drivers/staging/media/mn88472/mn88472.c576
-rw-r--r--drivers/staging/media/mn88472/mn88472_priv.h39
-rw-r--r--drivers/staging/media/mx2/Kconfig15
-rw-r--r--drivers/staging/media/mx2/Makefile3
-rw-r--r--drivers/staging/media/mx2/TODO10
-rw-r--r--drivers/staging/media/mx2/mx2_camera.c1636
-rw-r--r--drivers/staging/media/mx3/Kconfig15
-rw-r--r--drivers/staging/media/mx3/Makefile3
-rw-r--r--drivers/staging/media/mx3/TODO10
-rw-r--r--drivers/staging/media/mx3/mx3_camera.c1264
-rw-r--r--drivers/staging/media/omap1/Kconfig13
-rw-r--r--drivers/staging/media/omap1/Makefile3
-rw-r--r--drivers/staging/media/omap1/TODO8
-rw-r--r--drivers/staging/media/omap1/omap1_camera.c1702
-rw-r--r--drivers/staging/media/timb/Kconfig11
-rw-r--r--drivers/staging/media/timb/Makefile1
-rw-r--r--drivers/staging/media/timb/timblogiw.c870
-rw-r--r--drivers/staging/wilc1000/wilc_msgqueue.c144
-rw-r--r--drivers/staging/wilc1000/wilc_msgqueue.h28
-rw-r--r--drivers/tty/serial/msm_serial.h184
-rw-r--r--drivers/usb/dwc3/platform_data.h53
-rw-r--r--drivers/usb/gadget/udc/udc-core.c800
-rw-r--r--drivers/usb/misc/usbled.c273
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h259
85 files changed, 10 insertions, 33590 deletions
diff --git a/drivers/acpi/int340x_thermal.c b/drivers/acpi/int340x_thermal.c
deleted file mode 100644
index 33505c651..000000000
--- a/drivers/acpi/int340x_thermal.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * ACPI support for int340x thermal drivers
- *
- * Copyright (C) 2014, Intel Corporation
- * Authors: Zhang Rui <rui.zhang@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/acpi.h>
-#include <linux/module.h>
-
-#include "internal.h"
-
-#define INT3401_DEVICE 0X01
-static const struct acpi_device_id int340x_thermal_device_ids[] = {
- {"INT3400"},
- {"INT3401", INT3401_DEVICE},
- {"INT3402"},
- {"INT3403"},
- {"INT3404"},
- {"INT3406"},
- {"INT3407"},
- {"INT3408"},
- {"INT3409"},
- {"INT340A"},
- {"INT340B"},
- {""},
-};
-
-static int int340x_thermal_handler_attach(struct acpi_device *adev,
- const struct acpi_device_id *id)
-{
- if (IS_ENABLED(CONFIG_INT340X_THERMAL))
- acpi_create_platform_device(adev);
- /* Intel SoC DTS thermal driver needs INT3401 to set IRQ descriptor */
- else if (IS_ENABLED(CONFIG_INTEL_SOC_DTS_THERMAL) &&
- id->driver_data == INT3401_DEVICE)
- acpi_create_platform_device(adev);
- return 1;
-}
-
-static struct acpi_scan_handler int340x_thermal_handler = {
- .ids = int340x_thermal_device_ids,
- .attach = int340x_thermal_handler_attach,
-};
-
-void __init acpi_int340x_thermal_init(void)
-{
- acpi_scan_add_handler(&int340x_thermal_handler);
-}
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
deleted file mode 100644
index 375c10f38..000000000
--- a/drivers/acpi/nfit.c
+++ /dev/null
@@ -1,2714 +0,0 @@
-/*
- * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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 <linux/list_sort.h>
-#include <linux/libnvdimm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/ndctl.h>
-#include <linux/delay.h>
-#include <linux/list.h>
-#include <linux/acpi.h>
-#include <linux/sort.h>
-#include <linux/pmem.h>
-#include <linux/io.h>
-#include <linux/nd.h>
-#include <asm/cacheflush.h>
-#include "nfit.h"
-
-/*
- * For readq() and writeq() on 32-bit builds, the hi-lo, lo-hi order is
- * irrelevant.
- */
-#include <linux/io-64-nonatomic-hi-lo.h>
-
-static bool force_enable_dimms;
-module_param(force_enable_dimms, bool, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(force_enable_dimms, "Ignore _STA (ACPI DIMM device) status");
-
-static unsigned int scrub_timeout = NFIT_ARS_TIMEOUT;
-module_param(scrub_timeout, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(scrub_timeout, "Initial scrub timeout in seconds");
-
-/* after three payloads of overflow, it's dead jim */
-static unsigned int scrub_overflow_abort = 3;
-module_param(scrub_overflow_abort, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(scrub_overflow_abort,
- "Number of times we overflow ARS results before abort");
-
-static bool disable_vendor_specific;
-module_param(disable_vendor_specific, bool, S_IRUGO);
-MODULE_PARM_DESC(disable_vendor_specific,
- "Limit commands to the publicly specified set\n");
-
-static struct workqueue_struct *nfit_wq;
-
-struct nfit_table_prev {
- struct list_head spas;
- struct list_head memdevs;
- struct list_head dcrs;
- struct list_head bdws;
- struct list_head idts;
- struct list_head flushes;
-};
-
-static u8 nfit_uuid[NFIT_UUID_MAX][16];
-
-const u8 *to_nfit_uuid(enum nfit_uuids id)
-{
- return nfit_uuid[id];
-}
-EXPORT_SYMBOL(to_nfit_uuid);
-
-static struct acpi_nfit_desc *to_acpi_nfit_desc(
- struct nvdimm_bus_descriptor *nd_desc)
-{
- return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
-}
-
-static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
-{
- struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
-
- /*
- * If provider == 'ACPI.NFIT' we can assume 'dev' is a struct
- * acpi_device.
- */
- if (!nd_desc->provider_name
- || strcmp(nd_desc->provider_name, "ACPI.NFIT") != 0)
- return NULL;
-
- return to_acpi_device(acpi_desc->dev);
-}
-
-static int xlat_status(void *buf, unsigned int cmd)
-{
- struct nd_cmd_clear_error *clear_err;
- struct nd_cmd_ars_status *ars_status;
- struct nd_cmd_ars_start *ars_start;
- struct nd_cmd_ars_cap *ars_cap;
- u16 flags;
-
- switch (cmd) {
- case ND_CMD_ARS_CAP:
- ars_cap = buf;
- if ((ars_cap->status & 0xffff) == NFIT_ARS_CAP_NONE)
- return -ENOTTY;
-
- /* Command failed */
- if (ars_cap->status & 0xffff)
- return -EIO;
-
- /* No supported scan types for this range */
- flags = ND_ARS_PERSISTENT | ND_ARS_VOLATILE;
- if ((ars_cap->status >> 16 & flags) == 0)
- return -ENOTTY;
- break;
- case ND_CMD_ARS_START:
- ars_start = buf;
- /* ARS is in progress */
- if ((ars_start->status & 0xffff) == NFIT_ARS_START_BUSY)
- return -EBUSY;
-
- /* Command failed */
- if (ars_start->status & 0xffff)
- return -EIO;
- break;
- case ND_CMD_ARS_STATUS:
- ars_status = buf;
- /* Command failed */
- if (ars_status->status & 0xffff)
- return -EIO;
- /* Check extended status (Upper two bytes) */
- if (ars_status->status == NFIT_ARS_STATUS_DONE)
- return 0;
-
- /* ARS is in progress */
- if (ars_status->status == NFIT_ARS_STATUS_BUSY)
- return -EBUSY;
-
- /* No ARS performed for the current boot */
- if (ars_status->status == NFIT_ARS_STATUS_NONE)
- return -EAGAIN;
-
- /*
- * ARS interrupted, either we overflowed or some other
- * agent wants the scan to stop. If we didn't overflow
- * then just continue with the returned results.
- */
- if (ars_status->status == NFIT_ARS_STATUS_INTR) {
- if (ars_status->flags & NFIT_ARS_F_OVERFLOW)
- return -ENOSPC;
- return 0;
- }
-
- /* Unknown status */
- if (ars_status->status >> 16)
- return -EIO;
- break;
- case ND_CMD_CLEAR_ERROR:
- clear_err = buf;
- if (clear_err->status & 0xffff)
- return -EIO;
- if (!clear_err->cleared)
- return -EIO;
- if (clear_err->length > clear_err->cleared)
- return clear_err->cleared;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
- struct nvdimm *nvdimm, unsigned int cmd, void *buf,
- unsigned int buf_len, int *cmd_rc)
-{
- struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
- union acpi_object in_obj, in_buf, *out_obj;
- const struct nd_cmd_desc *desc = NULL;
- struct device *dev = acpi_desc->dev;
- struct nd_cmd_pkg *call_pkg = NULL;
- const char *cmd_name, *dimm_name;
- unsigned long cmd_mask, dsm_mask;
- acpi_handle handle;
- unsigned int func;
- const u8 *uuid;
- u32 offset;
- int rc, i;
-
- func = cmd;
- if (cmd == ND_CMD_CALL) {
- call_pkg = buf;
- func = call_pkg->nd_command;
- }
-
- if (nvdimm) {
- struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
- struct acpi_device *adev = nfit_mem->adev;
-
- if (!adev)
- return -ENOTTY;
- if (call_pkg && nfit_mem->family != call_pkg->nd_family)
- return -ENOTTY;
-
- dimm_name = nvdimm_name(nvdimm);
- cmd_name = nvdimm_cmd_name(cmd);
- cmd_mask = nvdimm_cmd_mask(nvdimm);
- dsm_mask = nfit_mem->dsm_mask;
- desc = nd_cmd_dimm_desc(cmd);
- uuid = to_nfit_uuid(nfit_mem->family);
- handle = adev->handle;
- } else {
- struct acpi_device *adev = to_acpi_dev(acpi_desc);
-
- cmd_name = nvdimm_bus_cmd_name(cmd);
- cmd_mask = nd_desc->cmd_mask;
- dsm_mask = cmd_mask;
- desc = nd_cmd_bus_desc(cmd);
- uuid = to_nfit_uuid(NFIT_DEV_BUS);
- handle = adev->handle;
- dimm_name = "bus";
- }
-
- if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
- return -ENOTTY;
-
- if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask))
- return -ENOTTY;
-
- in_obj.type = ACPI_TYPE_PACKAGE;
- in_obj.package.count = 1;
- in_obj.package.elements = &in_buf;
- in_buf.type = ACPI_TYPE_BUFFER;
- in_buf.buffer.pointer = buf;
- in_buf.buffer.length = 0;
-
- /* libnvdimm has already validated the input envelope */
- for (i = 0; i < desc->in_num; i++)
- in_buf.buffer.length += nd_cmd_in_size(nvdimm, cmd, desc,
- i, buf);
-
- if (call_pkg) {
- /* skip over package wrapper */
- in_buf.buffer.pointer = (void *) &call_pkg->nd_payload;
- in_buf.buffer.length = call_pkg->nd_size_in;
- }
-
- if (IS_ENABLED(CONFIG_ACPI_NFIT_DEBUG)) {
- dev_dbg(dev, "%s:%s cmd: %d: func: %d input length: %d\n",
- __func__, dimm_name, cmd, func,
- in_buf.buffer.length);
- print_hex_dump_debug("nvdimm in ", DUMP_PREFIX_OFFSET, 4, 4,
- in_buf.buffer.pointer,
- min_t(u32, 256, in_buf.buffer.length), true);
- }
-
- out_obj = acpi_evaluate_dsm(handle, uuid, 1, func, &in_obj);
- if (!out_obj) {
- dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name,
- cmd_name);
- return -EINVAL;
- }
-
- if (call_pkg) {
- call_pkg->nd_fw_size = out_obj->buffer.length;
- memcpy(call_pkg->nd_payload + call_pkg->nd_size_in,
- out_obj->buffer.pointer,
- min(call_pkg->nd_fw_size, call_pkg->nd_size_out));
-
- ACPI_FREE(out_obj);
- /*
- * Need to support FW function w/o known size in advance.
- * Caller can determine required size based upon nd_fw_size.
- * If we return an error (like elsewhere) then caller wouldn't
- * be able to rely upon data returned to make calculation.
- */
- return 0;
- }
-
- if (out_obj->package.type != ACPI_TYPE_BUFFER) {
- dev_dbg(dev, "%s:%s unexpected output object type cmd: %s type: %d\n",
- __func__, dimm_name, cmd_name, out_obj->type);
- rc = -EINVAL;
- goto out;
- }
-
- if (IS_ENABLED(CONFIG_ACPI_NFIT_DEBUG)) {
- dev_dbg(dev, "%s:%s cmd: %s output length: %d\n", __func__,
- dimm_name, cmd_name, out_obj->buffer.length);
- print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4,
- 4, out_obj->buffer.pointer, min_t(u32, 128,
- out_obj->buffer.length), true);
- }
-
- for (i = 0, offset = 0; i < desc->out_num; i++) {
- u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf,
- (u32 *) out_obj->buffer.pointer);
-
- if (offset + out_size > out_obj->buffer.length) {
- dev_dbg(dev, "%s:%s output object underflow cmd: %s field: %d\n",
- __func__, dimm_name, cmd_name, i);
- break;
- }
-
- if (in_buf.buffer.length + offset + out_size > buf_len) {
- dev_dbg(dev, "%s:%s output overrun cmd: %s field: %d\n",
- __func__, dimm_name, cmd_name, i);
- rc = -ENXIO;
- goto out;
- }
- memcpy(buf + in_buf.buffer.length + offset,
- out_obj->buffer.pointer + offset, out_size);
- offset += out_size;
- }
- if (offset + in_buf.buffer.length < buf_len) {
- if (i >= 1) {
- /*
- * status valid, return the number of bytes left
- * unfilled in the output buffer
- */
- rc = buf_len - offset - in_buf.buffer.length;
- if (cmd_rc)
- *cmd_rc = xlat_status(buf, cmd);
- } else {
- dev_err(dev, "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n",
- __func__, dimm_name, cmd_name, buf_len,
- offset);
- rc = -ENXIO;
- }
- } else {
- rc = 0;
- if (cmd_rc)
- *cmd_rc = xlat_status(buf, cmd);
- }
-
- out:
- ACPI_FREE(out_obj);
-
- return rc;
-}
-
-static const char *spa_type_name(u16 type)
-{
- static const char *to_name[] = {
- [NFIT_SPA_VOLATILE] = "volatile",
- [NFIT_SPA_PM] = "pmem",
- [NFIT_SPA_DCR] = "dimm-control-region",
- [NFIT_SPA_BDW] = "block-data-window",
- [NFIT_SPA_VDISK] = "volatile-disk",
- [NFIT_SPA_VCD] = "volatile-cd",
- [NFIT_SPA_PDISK] = "persistent-disk",
- [NFIT_SPA_PCD] = "persistent-cd",
-
- };
-
- if (type > NFIT_SPA_PCD)
- return "unknown";
-
- return to_name[type];
-}
-
-static int nfit_spa_type(struct acpi_nfit_system_address *spa)
-{
- int i;
-
- for (i = 0; i < NFIT_UUID_MAX; i++)
- if (memcmp(to_nfit_uuid(i), spa->range_guid, 16) == 0)
- return i;
- return -1;
-}
-
-static bool add_spa(struct acpi_nfit_desc *acpi_desc,
- struct nfit_table_prev *prev,
- struct acpi_nfit_system_address *spa)
-{
- size_t length = min_t(size_t, sizeof(*spa), spa->header.length);
- struct device *dev = acpi_desc->dev;
- struct nfit_spa *nfit_spa;
-
- list_for_each_entry(nfit_spa, &prev->spas, list) {
- if (memcmp(nfit_spa->spa, spa, length) == 0) {
- list_move_tail(&nfit_spa->list, &acpi_desc->spas);
- return true;
- }
- }
-
- nfit_spa = devm_kzalloc(dev, sizeof(*nfit_spa), GFP_KERNEL);
- if (!nfit_spa)
- return false;
- INIT_LIST_HEAD(&nfit_spa->list);
- nfit_spa->spa = spa;
- list_add_tail(&nfit_spa->list, &acpi_desc->spas);
- dev_dbg(dev, "%s: spa index: %d type: %s\n", __func__,
- spa->range_index,
- spa_type_name(nfit_spa_type(spa)));
- return true;
-}
-
-static bool add_memdev(struct acpi_nfit_desc *acpi_desc,
- struct nfit_table_prev *prev,
- struct acpi_nfit_memory_map *memdev)
-{
- size_t length = min_t(size_t, sizeof(*memdev), memdev->header.length);
- struct device *dev = acpi_desc->dev;
- struct nfit_memdev *nfit_memdev;
-
- list_for_each_entry(nfit_memdev, &prev->memdevs, list)
- if (memcmp(nfit_memdev->memdev, memdev, length) == 0) {
- list_move_tail(&nfit_memdev->list, &acpi_desc->memdevs);
- return true;
- }
-
- nfit_memdev = devm_kzalloc(dev, sizeof(*nfit_memdev), GFP_KERNEL);
- if (!nfit_memdev)
- return false;
- INIT_LIST_HEAD(&nfit_memdev->list);
- nfit_memdev->memdev = memdev;
- list_add_tail(&nfit_memdev->list, &acpi_desc->memdevs);
- dev_dbg(dev, "%s: memdev handle: %#x spa: %d dcr: %d\n",
- __func__, memdev->device_handle, memdev->range_index,
- memdev->region_index);
- return true;
-}
-
-static bool add_dcr(struct acpi_nfit_desc *acpi_desc,
- struct nfit_table_prev *prev,
- struct acpi_nfit_control_region *dcr)
-{
- size_t length = min_t(size_t, sizeof(*dcr), dcr->header.length);
- struct device *dev = acpi_desc->dev;
- struct nfit_dcr *nfit_dcr;
-
- list_for_each_entry(nfit_dcr, &prev->dcrs, list)
- if (memcmp(nfit_dcr->dcr, dcr, length) == 0) {
- list_move_tail(&nfit_dcr->list, &acpi_desc->dcrs);
- return true;
- }
-
- nfit_dcr = devm_kzalloc(dev, sizeof(*nfit_dcr), GFP_KERNEL);
- if (!nfit_dcr)
- return false;
- INIT_LIST_HEAD(&nfit_dcr->list);
- nfit_dcr->dcr = dcr;
- list_add_tail(&nfit_dcr->list, &acpi_desc->dcrs);
- dev_dbg(dev, "%s: dcr index: %d windows: %d\n", __func__,
- dcr->region_index, dcr->windows);
- return true;
-}
-
-static bool add_bdw(struct acpi_nfit_desc *acpi_desc,
- struct nfit_table_prev *prev,
- struct acpi_nfit_data_region *bdw)
-{
- size_t length = min_t(size_t, sizeof(*bdw), bdw->header.length);
- struct device *dev = acpi_desc->dev;
- struct nfit_bdw *nfit_bdw;
-
- list_for_each_entry(nfit_bdw, &prev->bdws, list)
- if (memcmp(nfit_bdw->bdw, bdw, length) == 0) {
- list_move_tail(&nfit_bdw->list, &acpi_desc->bdws);
- return true;
- }
-
- nfit_bdw = devm_kzalloc(dev, sizeof(*nfit_bdw), GFP_KERNEL);
- if (!nfit_bdw)
- return false;
- INIT_LIST_HEAD(&nfit_bdw->list);
- nfit_bdw->bdw = bdw;
- list_add_tail(&nfit_bdw->list, &acpi_desc->bdws);
- dev_dbg(dev, "%s: bdw dcr: %d windows: %d\n", __func__,
- bdw->region_index, bdw->windows);
- return true;
-}
-
-static bool add_idt(struct acpi_nfit_desc *acpi_desc,
- struct nfit_table_prev *prev,
- struct acpi_nfit_interleave *idt)
-{
- size_t length = min_t(size_t, sizeof(*idt), idt->header.length);
- struct device *dev = acpi_desc->dev;
- struct nfit_idt *nfit_idt;
-
- list_for_each_entry(nfit_idt, &prev->idts, list)
- if (memcmp(nfit_idt->idt, idt, length) == 0) {
- list_move_tail(&nfit_idt->list, &acpi_desc->idts);
- return true;
- }
-
- nfit_idt = devm_kzalloc(dev, sizeof(*nfit_idt), GFP_KERNEL);
- if (!nfit_idt)
- return false;
- INIT_LIST_HEAD(&nfit_idt->list);
- nfit_idt->idt = idt;
- list_add_tail(&nfit_idt->list, &acpi_desc->idts);
- dev_dbg(dev, "%s: idt index: %d num_lines: %d\n", __func__,
- idt->interleave_index, idt->line_count);
- return true;
-}
-
-static bool add_flush(struct acpi_nfit_desc *acpi_desc,
- struct nfit_table_prev *prev,
- struct acpi_nfit_flush_address *flush)
-{
- size_t length = min_t(size_t, sizeof(*flush), flush->header.length);
- struct device *dev = acpi_desc->dev;
- struct nfit_flush *nfit_flush;
-
- list_for_each_entry(nfit_flush, &prev->flushes, list)
- if (memcmp(nfit_flush->flush, flush, length) == 0) {
- list_move_tail(&nfit_flush->list, &acpi_desc->flushes);
- return true;
- }
-
- nfit_flush = devm_kzalloc(dev, sizeof(*nfit_flush), GFP_KERNEL);
- if (!nfit_flush)
- return false;
- INIT_LIST_HEAD(&nfit_flush->list);
- nfit_flush->flush = flush;
- list_add_tail(&nfit_flush->list, &acpi_desc->flushes);
- dev_dbg(dev, "%s: nfit_flush handle: %d hint_count: %d\n", __func__,
- flush->device_handle, flush->hint_count);
- return true;
-}
-
-static void *add_table(struct acpi_nfit_desc *acpi_desc,
- struct nfit_table_prev *prev, void *table, const void *end)
-{
- struct device *dev = acpi_desc->dev;
- struct acpi_nfit_header *hdr;
- void *err = ERR_PTR(-ENOMEM);
-
- if (table >= end)
- return NULL;
-
- hdr = table;
- if (!hdr->length) {
- dev_warn(dev, "found a zero length table '%d' parsing nfit\n",
- hdr->type);
- return NULL;
- }
-
- switch (hdr->type) {
- case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
- if (!add_spa(acpi_desc, prev, table))
- return err;
- break;
- case ACPI_NFIT_TYPE_MEMORY_MAP:
- if (!add_memdev(acpi_desc, prev, table))
- return err;
- break;
- case ACPI_NFIT_TYPE_CONTROL_REGION:
- if (!add_dcr(acpi_desc, prev, table))
- return err;
- break;
- case ACPI_NFIT_TYPE_DATA_REGION:
- if (!add_bdw(acpi_desc, prev, table))
- return err;
- break;
- case ACPI_NFIT_TYPE_INTERLEAVE:
- if (!add_idt(acpi_desc, prev, table))
- return err;
- break;
- case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
- if (!add_flush(acpi_desc, prev, table))
- return err;
- break;
- case ACPI_NFIT_TYPE_SMBIOS:
- dev_dbg(dev, "%s: smbios\n", __func__);
- break;
- default:
- dev_err(dev, "unknown table '%d' parsing nfit\n", hdr->type);
- break;
- }
-
- return table + hdr->length;
-}
-
-static void nfit_mem_find_spa_bdw(struct acpi_nfit_desc *acpi_desc,
- struct nfit_mem *nfit_mem)
-{
- u32 device_handle = __to_nfit_memdev(nfit_mem)->device_handle;
- u16 dcr = nfit_mem->dcr->region_index;
- struct nfit_spa *nfit_spa;
-
- list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
- u16 range_index = nfit_spa->spa->range_index;
- int type = nfit_spa_type(nfit_spa->spa);
- struct nfit_memdev *nfit_memdev;
-
- if (type != NFIT_SPA_BDW)
- continue;
-
- list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
- if (nfit_memdev->memdev->range_index != range_index)
- continue;
- if (nfit_memdev->memdev->device_handle != device_handle)
- continue;
- if (nfit_memdev->memdev->region_index != dcr)
- continue;
-
- nfit_mem->spa_bdw = nfit_spa->spa;
- return;
- }
- }
-
- dev_dbg(acpi_desc->dev, "SPA-BDW not found for SPA-DCR %d\n",
- nfit_mem->spa_dcr->range_index);
- nfit_mem->bdw = NULL;
-}
-
-static void nfit_mem_init_bdw(struct acpi_nfit_desc *acpi_desc,
- struct nfit_mem *nfit_mem, struct acpi_nfit_system_address *spa)
-{
- u16 dcr = __to_nfit_memdev(nfit_mem)->region_index;
- struct nfit_memdev *nfit_memdev;
- struct nfit_flush *nfit_flush;
- struct nfit_bdw *nfit_bdw;
- struct nfit_idt *nfit_idt;
- u16 idt_idx, range_index;
-
- list_for_each_entry(nfit_bdw, &acpi_desc->bdws, list) {
- if (nfit_bdw->bdw->region_index != dcr)
- continue;
- nfit_mem->bdw = nfit_bdw->bdw;
- break;
- }
-
- if (!nfit_mem->bdw)
- return;
-
- nfit_mem_find_spa_bdw(acpi_desc, nfit_mem);
-
- if (!nfit_mem->spa_bdw)
- return;
-
- range_index = nfit_mem->spa_bdw->range_index;
- list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
- if (nfit_memdev->memdev->range_index != range_index ||
- nfit_memdev->memdev->region_index != dcr)
- continue;
- nfit_mem->memdev_bdw = nfit_memdev->memdev;
- idt_idx = nfit_memdev->memdev->interleave_index;
- list_for_each_entry(nfit_idt, &acpi_desc->idts, list) {
- if (nfit_idt->idt->interleave_index != idt_idx)
- continue;
- nfit_mem->idt_bdw = nfit_idt->idt;
- break;
- }
-
- list_for_each_entry(nfit_flush, &acpi_desc->flushes, list) {
- if (nfit_flush->flush->device_handle !=
- nfit_memdev->memdev->device_handle)
- continue;
- nfit_mem->nfit_flush = nfit_flush;
- break;
- }
- break;
- }
-}
-
-static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
- struct acpi_nfit_system_address *spa)
-{
- struct nfit_mem *nfit_mem, *found;
- struct nfit_memdev *nfit_memdev;
- int type = nfit_spa_type(spa);
-
- switch (type) {
- case NFIT_SPA_DCR:
- case NFIT_SPA_PM:
- break;
- default:
- return 0;
- }
-
- list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
- struct nfit_dcr *nfit_dcr;
- u32 device_handle;
- u16 dcr;
-
- if (nfit_memdev->memdev->range_index != spa->range_index)
- continue;
- found = NULL;
- dcr = nfit_memdev->memdev->region_index;
- device_handle = nfit_memdev->memdev->device_handle;
- list_for_each_entry(nfit_mem, &acpi_desc->dimms, list)
- if (__to_nfit_memdev(nfit_mem)->device_handle
- == device_handle) {
- found = nfit_mem;
- break;
- }
-
- if (found)
- nfit_mem = found;
- else {
- nfit_mem = devm_kzalloc(acpi_desc->dev,
- sizeof(*nfit_mem), GFP_KERNEL);
- if (!nfit_mem)
- return -ENOMEM;
- INIT_LIST_HEAD(&nfit_mem->list);
- nfit_mem->acpi_desc = acpi_desc;
- list_add(&nfit_mem->list, &acpi_desc->dimms);
- }
-
- list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
- if (nfit_dcr->dcr->region_index != dcr)
- continue;
- /*
- * Record the control region for the dimm. For
- * the ACPI 6.1 case, where there are separate
- * control regions for the pmem vs blk
- * interfaces, be sure to record the extended
- * blk details.
- */
- if (!nfit_mem->dcr)
- nfit_mem->dcr = nfit_dcr->dcr;
- else if (nfit_mem->dcr->windows == 0
- && nfit_dcr->dcr->windows)
- nfit_mem->dcr = nfit_dcr->dcr;
- break;
- }
-
- if (dcr && !nfit_mem->dcr) {
- dev_err(acpi_desc->dev, "SPA %d missing DCR %d\n",
- spa->range_index, dcr);
- return -ENODEV;
- }
-
- if (type == NFIT_SPA_DCR) {
- struct nfit_idt *nfit_idt;
- u16 idt_idx;
-
- /* multiple dimms may share a SPA when interleaved */
- nfit_mem->spa_dcr = spa;
- nfit_mem->memdev_dcr = nfit_memdev->memdev;
- idt_idx = nfit_memdev->memdev->interleave_index;
- list_for_each_entry(nfit_idt, &acpi_desc->idts, list) {
- if (nfit_idt->idt->interleave_index != idt_idx)
- continue;
- nfit_mem->idt_dcr = nfit_idt->idt;
- break;
- }
- nfit_mem_init_bdw(acpi_desc, nfit_mem, spa);
- } else {
- /*
- * A single dimm may belong to multiple SPA-PM
- * ranges, record at least one in addition to
- * any SPA-DCR range.
- */
- nfit_mem->memdev_pmem = nfit_memdev->memdev;
- }
- }
-
- return 0;
-}
-
-static int nfit_mem_cmp(void *priv, struct list_head *_a, struct list_head *_b)
-{
- struct nfit_mem *a = container_of(_a, typeof(*a), list);
- struct nfit_mem *b = container_of(_b, typeof(*b), list);
- u32 handleA, handleB;
-
- handleA = __to_nfit_memdev(a)->device_handle;
- handleB = __to_nfit_memdev(b)->device_handle;
- if (handleA < handleB)
- return -1;
- else if (handleA > handleB)
- return 1;
- return 0;
-}
-
-static int nfit_mem_init(struct acpi_nfit_desc *acpi_desc)
-{
- struct nfit_spa *nfit_spa;
-
- /*
- * For each SPA-DCR or SPA-PMEM address range find its
- * corresponding MEMDEV(s). From each MEMDEV find the
- * corresponding DCR. Then, if we're operating on a SPA-DCR,
- * try to find a SPA-BDW and a corresponding BDW that references
- * the DCR. Throw it all into an nfit_mem object. Note, that
- * BDWs are optional.
- */
- list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
- int rc;
-
- rc = nfit_mem_dcr_init(acpi_desc, nfit_spa->spa);
- if (rc)
- return rc;
- }
-
- list_sort(NULL, &acpi_desc->dimms, nfit_mem_cmp);
-
- return 0;
-}
-
-static ssize_t revision_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev);
- struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
- struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
-
- return sprintf(buf, "%d\n", acpi_desc->acpi_header.revision);
-}
-static DEVICE_ATTR_RO(revision);
-
-static struct attribute *acpi_nfit_attributes[] = {
- &dev_attr_revision.attr,
- NULL,
-};
-
-static struct attribute_group acpi_nfit_attribute_group = {
- .name = "nfit",
- .attrs = acpi_nfit_attributes,
-};
-
-static const struct attribute_group *acpi_nfit_attribute_groups[] = {
- &nvdimm_bus_attribute_group,
- &acpi_nfit_attribute_group,
- NULL,
-};
-
-static struct acpi_nfit_memory_map *to_nfit_memdev(struct device *dev)
-{
- struct nvdimm *nvdimm = to_nvdimm(dev);
- struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
-
- return __to_nfit_memdev(nfit_mem);
-}
-
-static struct acpi_nfit_control_region *to_nfit_dcr(struct device *dev)
-{
- struct nvdimm *nvdimm = to_nvdimm(dev);
- struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
-
- return nfit_mem->dcr;
-}
-
-static ssize_t handle_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_memory_map *memdev = to_nfit_memdev(dev);
-
- return sprintf(buf, "%#x\n", memdev->device_handle);
-}
-static DEVICE_ATTR_RO(handle);
-
-static ssize_t phys_id_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_memory_map *memdev = to_nfit_memdev(dev);
-
- return sprintf(buf, "%#x\n", memdev->physical_id);
-}
-static DEVICE_ATTR_RO(phys_id);
-
-static ssize_t vendor_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->vendor_id));
-}
-static DEVICE_ATTR_RO(vendor);
-
-static ssize_t rev_id_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->revision_id));
-}
-static DEVICE_ATTR_RO(rev_id);
-
-static ssize_t device_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->device_id));
-}
-static DEVICE_ATTR_RO(device);
-
-static ssize_t subsystem_vendor_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->subsystem_vendor_id));
-}
-static DEVICE_ATTR_RO(subsystem_vendor);
-
-static ssize_t subsystem_rev_id_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- return sprintf(buf, "0x%04x\n",
- be16_to_cpu(dcr->subsystem_revision_id));
-}
-static DEVICE_ATTR_RO(subsystem_rev_id);
-
-static ssize_t subsystem_device_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->subsystem_device_id));
-}
-static DEVICE_ATTR_RO(subsystem_device);
-
-static int num_nvdimm_formats(struct nvdimm *nvdimm)
-{
- struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
- int formats = 0;
-
- if (nfit_mem->memdev_pmem)
- formats++;
- if (nfit_mem->memdev_bdw)
- formats++;
- return formats;
-}
-
-static ssize_t format_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- return sprintf(buf, "0x%04x\n", le16_to_cpu(dcr->code));
-}
-static DEVICE_ATTR_RO(format);
-
-static ssize_t format1_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- u32 handle;
- ssize_t rc = -ENXIO;
- struct nfit_mem *nfit_mem;
- struct nfit_memdev *nfit_memdev;
- struct acpi_nfit_desc *acpi_desc;
- struct nvdimm *nvdimm = to_nvdimm(dev);
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- nfit_mem = nvdimm_provider_data(nvdimm);
- acpi_desc = nfit_mem->acpi_desc;
- handle = to_nfit_memdev(dev)->device_handle;
-
- /* assumes DIMMs have at most 2 published interface codes */
- mutex_lock(&acpi_desc->init_mutex);
- list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
- struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev;
- struct nfit_dcr *nfit_dcr;
-
- if (memdev->device_handle != handle)
- continue;
-
- list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
- if (nfit_dcr->dcr->region_index != memdev->region_index)
- continue;
- if (nfit_dcr->dcr->code == dcr->code)
- continue;
- rc = sprintf(buf, "0x%04x\n",
- le16_to_cpu(nfit_dcr->dcr->code));
- break;
- }
- if (rc != ENXIO)
- break;
- }
- mutex_unlock(&acpi_desc->init_mutex);
- return rc;
-}
-static DEVICE_ATTR_RO(format1);
-
-static ssize_t formats_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nvdimm *nvdimm = to_nvdimm(dev);
-
- return sprintf(buf, "%d\n", num_nvdimm_formats(nvdimm));
-}
-static DEVICE_ATTR_RO(formats);
-
-static ssize_t serial_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- return sprintf(buf, "0x%08x\n", be32_to_cpu(dcr->serial_number));
-}
-static DEVICE_ATTR_RO(serial);
-
-static ssize_t family_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nvdimm *nvdimm = to_nvdimm(dev);
- struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
-
- if (nfit_mem->family < 0)
- return -ENXIO;
- return sprintf(buf, "%d\n", nfit_mem->family);
-}
-static DEVICE_ATTR_RO(family);
-
-static ssize_t dsm_mask_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nvdimm *nvdimm = to_nvdimm(dev);
- struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
-
- if (nfit_mem->family < 0)
- return -ENXIO;
- return sprintf(buf, "%#lx\n", nfit_mem->dsm_mask);
-}
-static DEVICE_ATTR_RO(dsm_mask);
-
-static ssize_t flags_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- u16 flags = to_nfit_memdev(dev)->flags;
-
- return sprintf(buf, "%s%s%s%s%s\n",
- flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save_fail " : "",
- flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore_fail " : "",
- flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush_fail " : "",
- flags & ACPI_NFIT_MEM_NOT_ARMED ? "not_armed " : "",
- flags & ACPI_NFIT_MEM_HEALTH_OBSERVED ? "smart_event " : "");
-}
-static DEVICE_ATTR_RO(flags);
-
-static ssize_t id_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
-
- if (dcr->valid_fields & ACPI_NFIT_CONTROL_MFG_INFO_VALID)
- return sprintf(buf, "%04x-%02x-%04x-%08x\n",
- be16_to_cpu(dcr->vendor_id),
- dcr->manufacturing_location,
- be16_to_cpu(dcr->manufacturing_date),
- be32_to_cpu(dcr->serial_number));
- else
- return sprintf(buf, "%04x-%08x\n",
- be16_to_cpu(dcr->vendor_id),
- be32_to_cpu(dcr->serial_number));
-}
-static DEVICE_ATTR_RO(id);
-
-static struct attribute *acpi_nfit_dimm_attributes[] = {
- &dev_attr_handle.attr,
- &dev_attr_phys_id.attr,
- &dev_attr_vendor.attr,
- &dev_attr_device.attr,
- &dev_attr_rev_id.attr,
- &dev_attr_subsystem_vendor.attr,
- &dev_attr_subsystem_device.attr,
- &dev_attr_subsystem_rev_id.attr,
- &dev_attr_format.attr,
- &dev_attr_formats.attr,
- &dev_attr_format1.attr,
- &dev_attr_serial.attr,
- &dev_attr_flags.attr,
- &dev_attr_id.attr,
- &dev_attr_family.attr,
- &dev_attr_dsm_mask.attr,
- NULL,
-};
-
-static umode_t acpi_nfit_dimm_attr_visible(struct kobject *kobj,
- struct attribute *a, int n)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct nvdimm *nvdimm = to_nvdimm(dev);
-
- if (!to_nfit_dcr(dev))
- return 0;
- if (a == &dev_attr_format1.attr && num_nvdimm_formats(nvdimm) <= 1)
- return 0;
- return a->mode;
-}
-
-static struct attribute_group acpi_nfit_dimm_attribute_group = {
- .name = "nfit",
- .attrs = acpi_nfit_dimm_attributes,
- .is_visible = acpi_nfit_dimm_attr_visible,
-};
-
-static const struct attribute_group *acpi_nfit_dimm_attribute_groups[] = {
- &nvdimm_attribute_group,
- &nd_device_attribute_group,
- &acpi_nfit_dimm_attribute_group,
- NULL,
-};
-
-static struct nvdimm *acpi_nfit_dimm_by_handle(struct acpi_nfit_desc *acpi_desc,
- u32 device_handle)
-{
- struct nfit_mem *nfit_mem;
-
- list_for_each_entry(nfit_mem, &acpi_desc->dimms, list)
- if (__to_nfit_memdev(nfit_mem)->device_handle == device_handle)
- return nfit_mem->nvdimm;
-
- return NULL;
-}
-
-static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
- struct nfit_mem *nfit_mem, u32 device_handle)
-{
- struct acpi_device *adev, *adev_dimm;
- struct device *dev = acpi_desc->dev;
- unsigned long dsm_mask;
- const u8 *uuid;
- int i;
-
- /* nfit test assumes 1:1 relationship between commands and dsms */
- nfit_mem->dsm_mask = acpi_desc->dimm_cmd_force_en;
- nfit_mem->family = NVDIMM_FAMILY_INTEL;
- adev = to_acpi_dev(acpi_desc);
- if (!adev)
- return 0;
-
- adev_dimm = acpi_find_child_device(adev, device_handle, false);
- nfit_mem->adev = adev_dimm;
- if (!adev_dimm) {
- dev_err(dev, "no ACPI.NFIT device with _ADR %#x, disabling...\n",
- device_handle);
- return force_enable_dimms ? 0 : -ENODEV;
- }
-
- /*
- * Until standardization materializes we need to consider up to 3
- * different command sets. Note, that checking for function0 (bit0)
- * tells us if any commands are reachable through this uuid.
- */
- for (i = NVDIMM_FAMILY_INTEL; i <= NVDIMM_FAMILY_HPE2; i++)
- if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1))
- break;
-
- /* limit the supported commands to those that are publicly documented */
- nfit_mem->family = i;
- if (nfit_mem->family == NVDIMM_FAMILY_INTEL) {
- dsm_mask = 0x3fe;
- if (disable_vendor_specific)
- dsm_mask &= ~(1 << ND_CMD_VENDOR);
- } else if (nfit_mem->family == NVDIMM_FAMILY_HPE1)
- dsm_mask = 0x1c3c76;
- else if (nfit_mem->family == NVDIMM_FAMILY_HPE2) {
- dsm_mask = 0x1fe;
- if (disable_vendor_specific)
- dsm_mask &= ~(1 << 8);
- } else {
- dev_dbg(dev, "unknown dimm command family\n");
- nfit_mem->family = -1;
- /* DSMs are optional, continue loading the driver... */
- return 0;
- }
-
- uuid = to_nfit_uuid(nfit_mem->family);
- for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
- if (acpi_check_dsm(adev_dimm->handle, uuid, 1, 1ULL << i))
- set_bit(i, &nfit_mem->dsm_mask);
-
- return 0;
-}
-
-static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
-{
- struct nfit_mem *nfit_mem;
- int dimm_count = 0;
-
- list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
- unsigned long flags = 0, cmd_mask;
- struct nvdimm *nvdimm;
- u32 device_handle;
- u16 mem_flags;
- int rc;
-
- device_handle = __to_nfit_memdev(nfit_mem)->device_handle;
- nvdimm = acpi_nfit_dimm_by_handle(acpi_desc, device_handle);
- if (nvdimm) {
- dimm_count++;
- continue;
- }
-
- if (nfit_mem->bdw && nfit_mem->memdev_pmem)
- flags |= NDD_ALIASING;
-
- mem_flags = __to_nfit_memdev(nfit_mem)->flags;
- if (mem_flags & ACPI_NFIT_MEM_NOT_ARMED)
- flags |= NDD_UNARMED;
-
- rc = acpi_nfit_add_dimm(acpi_desc, nfit_mem, device_handle);
- if (rc)
- continue;
-
- /*
- * TODO: provide translation for non-NVDIMM_FAMILY_INTEL
- * devices (i.e. from nd_cmd to acpi_dsm) to standardize the
- * userspace interface.
- */
- cmd_mask = 1UL << ND_CMD_CALL;
- if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
- cmd_mask |= nfit_mem->dsm_mask;
-
- nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem,
- acpi_nfit_dimm_attribute_groups,
- flags, cmd_mask);
- if (!nvdimm)
- return -ENOMEM;
-
- nfit_mem->nvdimm = nvdimm;
- dimm_count++;
-
- if ((mem_flags & ACPI_NFIT_MEM_FAILED_MASK) == 0)
- continue;
-
- dev_info(acpi_desc->dev, "%s flags:%s%s%s%s\n",
- nvdimm_name(nvdimm),
- mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? " save_fail" : "",
- mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? " restore_fail":"",
- mem_flags & ACPI_NFIT_MEM_FLUSH_FAILED ? " flush_fail" : "",
- mem_flags & ACPI_NFIT_MEM_NOT_ARMED ? " not_armed" : "");
-
- }
-
- return nvdimm_bus_check_dimm_count(acpi_desc->nvdimm_bus, dimm_count);
-}
-
-static void acpi_nfit_init_dsms(struct acpi_nfit_desc *acpi_desc)
-{
- struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
- const u8 *uuid = to_nfit_uuid(NFIT_DEV_BUS);
- struct acpi_device *adev;
- int i;
-
- nd_desc->cmd_mask = acpi_desc->bus_cmd_force_en;
- adev = to_acpi_dev(acpi_desc);
- if (!adev)
- return;
-
- for (i = ND_CMD_ARS_CAP; i <= ND_CMD_CLEAR_ERROR; i++)
- if (acpi_check_dsm(adev->handle, uuid, 1, 1ULL << i))
- set_bit(i, &nd_desc->cmd_mask);
-}
-
-static ssize_t range_index_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct nd_region *nd_region = to_nd_region(dev);
- struct nfit_spa *nfit_spa = nd_region_provider_data(nd_region);
-
- return sprintf(buf, "%d\n", nfit_spa->spa->range_index);
-}
-static DEVICE_ATTR_RO(range_index);
-
-static struct attribute *acpi_nfit_region_attributes[] = {
- &dev_attr_range_index.attr,
- NULL,
-};
-
-static struct attribute_group acpi_nfit_region_attribute_group = {
- .name = "nfit",
- .attrs = acpi_nfit_region_attributes,
-};
-
-static const struct attribute_group *acpi_nfit_region_attribute_groups[] = {
- &nd_region_attribute_group,
- &nd_mapping_attribute_group,
- &nd_device_attribute_group,
- &nd_numa_attribute_group,
- &acpi_nfit_region_attribute_group,
- NULL,
-};
-
-/* enough info to uniquely specify an interleave set */
-struct nfit_set_info {
- struct nfit_set_info_map {
- u64 region_offset;
- u32 serial_number;
- u32 pad;
- } mapping[0];
-};
-
-static size_t sizeof_nfit_set_info(int num_mappings)
-{
- return sizeof(struct nfit_set_info)
- + num_mappings * sizeof(struct nfit_set_info_map);
-}
-
-static int cmp_map(const void *m0, const void *m1)
-{
- const struct nfit_set_info_map *map0 = m0;
- const struct nfit_set_info_map *map1 = m1;
-
- return memcmp(&map0->region_offset, &map1->region_offset,
- sizeof(u64));
-}
-
-/* Retrieve the nth entry referencing this spa */
-static struct acpi_nfit_memory_map *memdev_from_spa(
- struct acpi_nfit_desc *acpi_desc, u16 range_index, int n)
-{
- struct nfit_memdev *nfit_memdev;
-
- list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list)
- if (nfit_memdev->memdev->range_index == range_index)
- if (n-- == 0)
- return nfit_memdev->memdev;
- return NULL;
-}
-
-static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
- struct nd_region_desc *ndr_desc,
- struct acpi_nfit_system_address *spa)
-{
- int i, spa_type = nfit_spa_type(spa);
- struct device *dev = acpi_desc->dev;
- struct nd_interleave_set *nd_set;
- u16 nr = ndr_desc->num_mappings;
- struct nfit_set_info *info;
-
- if (spa_type == NFIT_SPA_PM || spa_type == NFIT_SPA_VOLATILE)
- /* pass */;
- else
- return 0;
-
- nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL);
- if (!nd_set)
- return -ENOMEM;
-
- info = devm_kzalloc(dev, sizeof_nfit_set_info(nr), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
- for (i = 0; i < nr; i++) {
- struct nd_mapping *nd_mapping = &ndr_desc->nd_mapping[i];
- struct nfit_set_info_map *map = &info->mapping[i];
- struct nvdimm *nvdimm = nd_mapping->nvdimm;
- struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
- struct acpi_nfit_memory_map *memdev = memdev_from_spa(acpi_desc,
- spa->range_index, i);
-
- if (!memdev || !nfit_mem->dcr) {
- dev_err(dev, "%s: failed to find DCR\n", __func__);
- return -ENODEV;
- }
-
- map->region_offset = memdev->region_offset;
- map->serial_number = nfit_mem->dcr->serial_number;
- }
-
- sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
- cmp_map, NULL);
- nd_set->cookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
- ndr_desc->nd_set = nd_set;
- devm_kfree(dev, info);
-
- return 0;
-}
-
-static u64 to_interleave_offset(u64 offset, struct nfit_blk_mmio *mmio)
-{
- struct acpi_nfit_interleave *idt = mmio->idt;
- u32 sub_line_offset, line_index, line_offset;
- u64 line_no, table_skip_count, table_offset;
-
- line_no = div_u64_rem(offset, mmio->line_size, &sub_line_offset);
- table_skip_count = div_u64_rem(line_no, mmio->num_lines, &line_index);
- line_offset = idt->line_offset[line_index]
- * mmio->line_size;
- table_offset = table_skip_count * mmio->table_size;
-
- return mmio->base_offset + line_offset + table_offset + sub_line_offset;
-}
-
-static void wmb_blk(struct nfit_blk *nfit_blk)
-{
-
- if (nfit_blk->nvdimm_flush) {
- /*
- * The first wmb() is needed to 'sfence' all previous writes
- * such that they are architecturally visible for the platform
- * buffer flush. Note that we've already arranged for pmem
- * writes to avoid the cache via arch_memcpy_to_pmem(). The
- * final wmb() ensures ordering for the NVDIMM flush write.
- */
- wmb();
- writeq(1, nfit_blk->nvdimm_flush);
- wmb();
- } else
- wmb_pmem();
-}
-
-static u32 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw)
-{
- struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR];
- u64 offset = nfit_blk->stat_offset + mmio->size * bw;
- const u32 STATUS_MASK = 0x80000037;
-
- if (mmio->num_lines)
- offset = to_interleave_offset(offset, mmio);
-
- return readl(mmio->addr.base + offset) & STATUS_MASK;
-}
-
-static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw,
- resource_size_t dpa, unsigned int len, unsigned int write)
-{
- u64 cmd, offset;
- struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR];
-
- enum {
- BCW_OFFSET_MASK = (1ULL << 48)-1,
- BCW_LEN_SHIFT = 48,
- BCW_LEN_MASK = (1ULL << 8) - 1,
- BCW_CMD_SHIFT = 56,
- };
-
- cmd = (dpa >> L1_CACHE_SHIFT) & BCW_OFFSET_MASK;
- len = len >> L1_CACHE_SHIFT;
- cmd |= ((u64) len & BCW_LEN_MASK) << BCW_LEN_SHIFT;
- cmd |= ((u64) write) << BCW_CMD_SHIFT;
-
- offset = nfit_blk->cmd_offset + mmio->size * bw;
- if (mmio->num_lines)
- offset = to_interleave_offset(offset, mmio);
-
- writeq(cmd, mmio->addr.base + offset);
- wmb_blk(nfit_blk);
-
- if (nfit_blk->dimm_flags & NFIT_BLK_DCR_LATCH)
- readq(mmio->addr.base + offset);
-}
-
-static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk,
- resource_size_t dpa, void *iobuf, size_t len, int rw,
- unsigned int lane)
-{
- struct nfit_blk_mmio *mmio = &nfit_blk->mmio[BDW];
- unsigned int copied = 0;
- u64 base_offset;
- int rc;
-
- base_offset = nfit_blk->bdw_offset + dpa % L1_CACHE_BYTES
- + lane * mmio->size;
- write_blk_ctl(nfit_blk, lane, dpa, len, rw);
- while (len) {
- unsigned int c;
- u64 offset;
-
- if (mmio->num_lines) {
- u32 line_offset;
-
- offset = to_interleave_offset(base_offset + copied,
- mmio);
- div_u64_rem(offset, mmio->line_size, &line_offset);
- c = min_t(size_t, len, mmio->line_size - line_offset);
- } else {
- offset = base_offset + nfit_blk->bdw_offset;
- c = len;
- }
-
- if (rw)
- memcpy_to_pmem(mmio->addr.aperture + offset,
- iobuf + copied, c);
- else {
- if (nfit_blk->dimm_flags & NFIT_BLK_READ_FLUSH)
- mmio_flush_range((void __force *)
- mmio->addr.aperture + offset, c);
-
- memcpy_from_pmem(iobuf + copied,
- mmio->addr.aperture + offset, c);
- }
-
- copied += c;
- len -= c;
- }
-
- if (rw)
- wmb_blk(nfit_blk);
-
- rc = read_blk_stat(nfit_blk, lane) ? -EIO : 0;
- return rc;
-}
-
-static int acpi_nfit_blk_region_do_io(struct nd_blk_region *ndbr,
- resource_size_t dpa, void *iobuf, u64 len, int rw)
-{
- struct nfit_blk *nfit_blk = nd_blk_region_provider_data(ndbr);
- struct nfit_blk_mmio *mmio = &nfit_blk->mmio[BDW];
- struct nd_region *nd_region = nfit_blk->nd_region;
- unsigned int lane, copied = 0;
- int rc = 0;
-
- lane = nd_region_acquire_lane(nd_region);
- while (len) {
- u64 c = min(len, mmio->size);
-
- rc = acpi_nfit_blk_single_io(nfit_blk, dpa + copied,
- iobuf + copied, c, rw, lane);
- if (rc)
- break;
-
- copied += c;
- len -= c;
- }
- nd_region_release_lane(nd_region, lane);
-
- return rc;
-}
-
-static void nfit_spa_mapping_release(struct kref *kref)
-{
- struct nfit_spa_mapping *spa_map = to_spa_map(kref);
- struct acpi_nfit_system_address *spa = spa_map->spa;
- struct acpi_nfit_desc *acpi_desc = spa_map->acpi_desc;
-
- WARN_ON(!mutex_is_locked(&acpi_desc->spa_map_mutex));
- dev_dbg(acpi_desc->dev, "%s: SPA%d\n", __func__, spa->range_index);
- if (spa_map->type == SPA_MAP_APERTURE)
- memunmap((void __force *)spa_map->addr.aperture);
- else
- iounmap(spa_map->addr.base);
- release_mem_region(spa->address, spa->length);
- list_del(&spa_map->list);
- kfree(spa_map);
-}
-
-static struct nfit_spa_mapping *find_spa_mapping(
- struct acpi_nfit_desc *acpi_desc,
- struct acpi_nfit_system_address *spa)
-{
- struct nfit_spa_mapping *spa_map;
-
- WARN_ON(!mutex_is_locked(&acpi_desc->spa_map_mutex));
- list_for_each_entry(spa_map, &acpi_desc->spa_maps, list)
- if (spa_map->spa == spa)
- return spa_map;
-
- return NULL;
-}
-
-static void nfit_spa_unmap(struct acpi_nfit_desc *acpi_desc,
- struct acpi_nfit_system_address *spa)
-{
- struct nfit_spa_mapping *spa_map;
-
- mutex_lock(&acpi_desc->spa_map_mutex);
- spa_map = find_spa_mapping(acpi_desc, spa);
-
- if (spa_map)
- kref_put(&spa_map->kref, nfit_spa_mapping_release);
- mutex_unlock(&acpi_desc->spa_map_mutex);
-}
-
-static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc,
- struct acpi_nfit_system_address *spa, enum spa_map_type type)
-{
- resource_size_t start = spa->address;
- resource_size_t n = spa->length;
- struct nfit_spa_mapping *spa_map;
- struct resource *res;
-
- WARN_ON(!mutex_is_locked(&acpi_desc->spa_map_mutex));
-
- spa_map = find_spa_mapping(acpi_desc, spa);
- if (spa_map) {
- kref_get(&spa_map->kref);
- return spa_map->addr.base;
- }
-
- spa_map = kzalloc(sizeof(*spa_map), GFP_KERNEL);
- if (!spa_map)
- return NULL;
-
- INIT_LIST_HEAD(&spa_map->list);
- spa_map->spa = spa;
- kref_init(&spa_map->kref);
- spa_map->acpi_desc = acpi_desc;
-
- res = request_mem_region(start, n, dev_name(acpi_desc->dev));
- if (!res)
- goto err_mem;
-
- spa_map->type = type;
- if (type == SPA_MAP_APERTURE)
- spa_map->addr.aperture = (void __pmem *)memremap(start, n,
- ARCH_MEMREMAP_PMEM);
- else
- spa_map->addr.base = ioremap_nocache(start, n);
-
-
- if (!spa_map->addr.base)
- goto err_map;
-
- list_add_tail(&spa_map->list, &acpi_desc->spa_maps);
- return spa_map->addr.base;
-
- err_map:
- release_mem_region(start, n);
- err_mem:
- kfree(spa_map);
- return NULL;
-}
-
-/**
- * nfit_spa_map - interleave-aware managed-mappings of acpi_nfit_system_address ranges
- * @nvdimm_bus: NFIT-bus that provided the spa table entry
- * @nfit_spa: spa table to map
- * @type: aperture or control region
- *
- * In the case where block-data-window apertures and
- * dimm-control-regions are interleaved they will end up sharing a
- * single request_mem_region() + ioremap() for the address range. In
- * the style of devm nfit_spa_map() mappings are automatically dropped
- * when all region devices referencing the same mapping are disabled /
- * unbound.
- */
-static void __iomem *nfit_spa_map(struct acpi_nfit_desc *acpi_desc,
- struct acpi_nfit_system_address *spa, enum spa_map_type type)
-{
- void __iomem *iomem;
-
- mutex_lock(&acpi_desc->spa_map_mutex);
- iomem = __nfit_spa_map(acpi_desc, spa, type);
- mutex_unlock(&acpi_desc->spa_map_mutex);
-
- return iomem;
-}
-
-static int nfit_blk_init_interleave(struct nfit_blk_mmio *mmio,
- struct acpi_nfit_interleave *idt, u16 interleave_ways)
-{
- if (idt) {
- mmio->num_lines = idt->line_count;
- mmio->line_size = idt->line_size;
- if (interleave_ways == 0)
- return -ENXIO;
- mmio->table_size = mmio->num_lines * interleave_ways
- * mmio->line_size;
- }
-
- return 0;
-}
-
-static int acpi_nfit_blk_get_flags(struct nvdimm_bus_descriptor *nd_desc,
- struct nvdimm *nvdimm, struct nfit_blk *nfit_blk)
-{
- struct nd_cmd_dimm_flags flags;
- int rc;
-
- memset(&flags, 0, sizeof(flags));
- rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_DIMM_FLAGS, &flags,
- sizeof(flags), NULL);
-
- if (rc >= 0 && flags.status == 0)
- nfit_blk->dimm_flags = flags.flags;
- else if (rc == -ENOTTY) {
- /* fall back to a conservative default */
- nfit_blk->dimm_flags = NFIT_BLK_DCR_LATCH | NFIT_BLK_READ_FLUSH;
- rc = 0;
- } else
- rc = -ENXIO;
-
- return rc;
-}
-
-static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
- struct device *dev)
-{
- struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
- struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
- struct nd_blk_region *ndbr = to_nd_blk_region(dev);
- struct nfit_flush *nfit_flush;
- struct nfit_blk_mmio *mmio;
- struct nfit_blk *nfit_blk;
- struct nfit_mem *nfit_mem;
- struct nvdimm *nvdimm;
- int rc;
-
- nvdimm = nd_blk_region_to_dimm(ndbr);
- nfit_mem = nvdimm_provider_data(nvdimm);
- if (!nfit_mem || !nfit_mem->dcr || !nfit_mem->bdw) {
- dev_dbg(dev, "%s: missing%s%s%s\n", __func__,
- nfit_mem ? "" : " nfit_mem",
- (nfit_mem && nfit_mem->dcr) ? "" : " dcr",
- (nfit_mem && nfit_mem->bdw) ? "" : " bdw");
- return -ENXIO;
- }
-
- nfit_blk = devm_kzalloc(dev, sizeof(*nfit_blk), GFP_KERNEL);
- if (!nfit_blk)
- return -ENOMEM;
- nd_blk_region_set_provider_data(ndbr, nfit_blk);
- nfit_blk->nd_region = to_nd_region(dev);
-
- /* map block aperture memory */
- nfit_blk->bdw_offset = nfit_mem->bdw->offset;
- mmio = &nfit_blk->mmio[BDW];
- mmio->addr.base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw,
- SPA_MAP_APERTURE);
- if (!mmio->addr.base) {
- dev_dbg(dev, "%s: %s failed to map bdw\n", __func__,
- nvdimm_name(nvdimm));
- return -ENOMEM;
- }
- mmio->size = nfit_mem->bdw->size;
- mmio->base_offset = nfit_mem->memdev_bdw->region_offset;
- mmio->idt = nfit_mem->idt_bdw;
- mmio->spa = nfit_mem->spa_bdw;
- rc = nfit_blk_init_interleave(mmio, nfit_mem->idt_bdw,
- nfit_mem->memdev_bdw->interleave_ways);
- if (rc) {
- dev_dbg(dev, "%s: %s failed to init bdw interleave\n",
- __func__, nvdimm_name(nvdimm));
- return rc;
- }
-
- /* map block control memory */
- nfit_blk->cmd_offset = nfit_mem->dcr->command_offset;
- nfit_blk->stat_offset = nfit_mem->dcr->status_offset;
- mmio = &nfit_blk->mmio[DCR];
- mmio->addr.base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr,
- SPA_MAP_CONTROL);
- if (!mmio->addr.base) {
- dev_dbg(dev, "%s: %s failed to map dcr\n", __func__,
- nvdimm_name(nvdimm));
- return -ENOMEM;
- }
- mmio->size = nfit_mem->dcr->window_size;
- mmio->base_offset = nfit_mem->memdev_dcr->region_offset;
- mmio->idt = nfit_mem->idt_dcr;
- mmio->spa = nfit_mem->spa_dcr;
- rc = nfit_blk_init_interleave(mmio, nfit_mem->idt_dcr,
- nfit_mem->memdev_dcr->interleave_ways);
- if (rc) {
- dev_dbg(dev, "%s: %s failed to init dcr interleave\n",
- __func__, nvdimm_name(nvdimm));
- return rc;
- }
-
- rc = acpi_nfit_blk_get_flags(nd_desc, nvdimm, nfit_blk);
- if (rc < 0) {
- dev_dbg(dev, "%s: %s failed get DIMM flags\n",
- __func__, nvdimm_name(nvdimm));
- return rc;
- }
-
- nfit_flush = nfit_mem->nfit_flush;
- if (nfit_flush && nfit_flush->flush->hint_count != 0) {
- nfit_blk->nvdimm_flush = devm_ioremap_nocache(dev,
- nfit_flush->flush->hint_address[0], 8);
- if (!nfit_blk->nvdimm_flush)
- return -ENOMEM;
- }
-
- if (!arch_has_wmb_pmem() && !nfit_blk->nvdimm_flush)
- dev_warn(dev, "unable to guarantee persistence of writes\n");
-
- if (mmio->line_size == 0)
- return 0;
-
- if ((u32) nfit_blk->cmd_offset % mmio->line_size
- + 8 > mmio->line_size) {
- dev_dbg(dev, "cmd_offset crosses interleave boundary\n");
- return -ENXIO;
- } else if ((u32) nfit_blk->stat_offset % mmio->line_size
- + 8 > mmio->line_size) {
- dev_dbg(dev, "stat_offset crosses interleave boundary\n");
- return -ENXIO;
- }
-
- return 0;
-}
-
-static void acpi_nfit_blk_region_disable(struct nvdimm_bus *nvdimm_bus,
- struct device *dev)
-{
- struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
- struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
- struct nd_blk_region *ndbr = to_nd_blk_region(dev);
- struct nfit_blk *nfit_blk = nd_blk_region_provider_data(ndbr);
- int i;
-
- if (!nfit_blk)
- return; /* never enabled */
-
- /* auto-free BLK spa mappings */
- for (i = 0; i < 2; i++) {
- struct nfit_blk_mmio *mmio = &nfit_blk->mmio[i];
-
- if (mmio->addr.base)
- nfit_spa_unmap(acpi_desc, mmio->spa);
- }
- nd_blk_region_set_provider_data(ndbr, NULL);
- /* devm will free nfit_blk */
-}
-
-static int ars_get_cap(struct acpi_nfit_desc *acpi_desc,
- struct nd_cmd_ars_cap *cmd, struct nfit_spa *nfit_spa)
-{
- struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
- int cmd_rc, rc;
-
- cmd->address = spa->address;
- cmd->length = spa->length;
- rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_CAP, cmd,
- sizeof(*cmd), &cmd_rc);
- if (rc < 0)
- return rc;
- return cmd_rc;
-}
-
-static int ars_start(struct acpi_nfit_desc *acpi_desc, struct nfit_spa *nfit_spa)
-{
- int rc;
- int cmd_rc;
- struct nd_cmd_ars_start ars_start;
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
- struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
-
- memset(&ars_start, 0, sizeof(ars_start));
- ars_start.address = spa->address;
- ars_start.length = spa->length;
- if (nfit_spa_type(spa) == NFIT_SPA_PM)
- ars_start.type = ND_ARS_PERSISTENT;
- else if (nfit_spa_type(spa) == NFIT_SPA_VOLATILE)
- ars_start.type = ND_ARS_VOLATILE;
- else
- return -ENOTTY;
-
- rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_START, &ars_start,
- sizeof(ars_start), &cmd_rc);
-
- if (rc < 0)
- return rc;
- return cmd_rc;
-}
-
-static int ars_continue(struct acpi_nfit_desc *acpi_desc)
-{
- int rc, cmd_rc;
- struct nd_cmd_ars_start ars_start;
- struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
- struct nd_cmd_ars_status *ars_status = acpi_desc->ars_status;
-
- memset(&ars_start, 0, sizeof(ars_start));
- ars_start.address = ars_status->restart_address;
- ars_start.length = ars_status->restart_length;
- ars_start.type = ars_status->type;
- rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_START, &ars_start,
- sizeof(ars_start), &cmd_rc);
- if (rc < 0)
- return rc;
- return cmd_rc;
-}
-
-static int ars_get_status(struct acpi_nfit_desc *acpi_desc)
-{
- struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
- struct nd_cmd_ars_status *ars_status = acpi_desc->ars_status;
- int rc, cmd_rc;
-
- rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, ars_status,
- acpi_desc->ars_status_size, &cmd_rc);
- if (rc < 0)
- return rc;
- return cmd_rc;
-}
-
-static int ars_status_process_records(struct nvdimm_bus *nvdimm_bus,
- struct nd_cmd_ars_status *ars_status)
-{
- int rc;
- u32 i;
-
- for (i = 0; i < ars_status->num_records; i++) {
- rc = nvdimm_bus_add_poison(nvdimm_bus,
- ars_status->records[i].err_address,
- ars_status->records[i].length);
- if (rc)
- return rc;
- }
-
- return 0;
-}
-
-static void acpi_nfit_remove_resource(void *data)
-{
- struct resource *res = data;
-
- remove_resource(res);
-}
-
-static int acpi_nfit_insert_resource(struct acpi_nfit_desc *acpi_desc,
- struct nd_region_desc *ndr_desc)
-{
- struct resource *res, *nd_res = ndr_desc->res;
- int is_pmem, ret;
-
- /* No operation if the region is already registered as PMEM */
- is_pmem = region_intersects(nd_res->start, resource_size(nd_res),
- IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY);
- if (is_pmem == REGION_INTERSECTS)
- return 0;
-
- res = devm_kzalloc(acpi_desc->dev, sizeof(*res), GFP_KERNEL);
- if (!res)
- return -ENOMEM;
-
- res->name = "Persistent Memory";
- res->start = nd_res->start;
- res->end = nd_res->end;
- res->flags = IORESOURCE_MEM;
- res->desc = IORES_DESC_PERSISTENT_MEMORY;
-
- ret = insert_resource(&iomem_resource, res);
- if (ret)
- return ret;
-
- ret = devm_add_action(acpi_desc->dev, acpi_nfit_remove_resource, res);
- if (ret) {
- remove_resource(res);
- return ret;
- }
-
- return 0;
-}
-
-static int acpi_nfit_init_mapping(struct acpi_nfit_desc *acpi_desc,
- struct nd_mapping *nd_mapping, struct nd_region_desc *ndr_desc,
- struct acpi_nfit_memory_map *memdev,
- struct nfit_spa *nfit_spa)
-{
- struct nvdimm *nvdimm = acpi_nfit_dimm_by_handle(acpi_desc,
- memdev->device_handle);
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
- struct nd_blk_region_desc *ndbr_desc;
- struct nfit_mem *nfit_mem;
- int blk_valid = 0;
-
- if (!nvdimm) {
- dev_err(acpi_desc->dev, "spa%d dimm: %#x not found\n",
- spa->range_index, memdev->device_handle);
- return -ENODEV;
- }
-
- nd_mapping->nvdimm = nvdimm;
- switch (nfit_spa_type(spa)) {
- case NFIT_SPA_PM:
- case NFIT_SPA_VOLATILE:
- nd_mapping->start = memdev->address;
- nd_mapping->size = memdev->region_size;
- break;
- case NFIT_SPA_DCR:
- nfit_mem = nvdimm_provider_data(nvdimm);
- if (!nfit_mem || !nfit_mem->bdw) {
- dev_dbg(acpi_desc->dev, "spa%d %s missing bdw\n",
- spa->range_index, nvdimm_name(nvdimm));
- } else {
- nd_mapping->size = nfit_mem->bdw->capacity;
- nd_mapping->start = nfit_mem->bdw->start_address;
- ndr_desc->num_lanes = nfit_mem->bdw->windows;
- blk_valid = 1;
- }
-
- ndr_desc->nd_mapping = nd_mapping;
- ndr_desc->num_mappings = blk_valid;
- ndbr_desc = to_blk_region_desc(ndr_desc);
- ndbr_desc->enable = acpi_nfit_blk_region_enable;
- ndbr_desc->disable = acpi_nfit_blk_region_disable;
- ndbr_desc->do_io = acpi_desc->blk_do_io;
- nfit_spa->nd_region = nvdimm_blk_region_create(acpi_desc->nvdimm_bus,
- ndr_desc);
- if (!nfit_spa->nd_region)
- return -ENOMEM;
- break;
- }
-
- return 0;
-}
-
-static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
- struct nfit_spa *nfit_spa)
-{
- static struct nd_mapping nd_mappings[ND_MAX_MAPPINGS];
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
- struct nd_blk_region_desc ndbr_desc;
- struct nd_region_desc *ndr_desc;
- struct nfit_memdev *nfit_memdev;
- struct nvdimm_bus *nvdimm_bus;
- struct resource res;
- int count = 0, rc;
-
- if (nfit_spa->nd_region)
- return 0;
-
- if (spa->range_index == 0) {
- dev_dbg(acpi_desc->dev, "%s: detected invalid spa index\n",
- __func__);
- return 0;
- }
-
- memset(&res, 0, sizeof(res));
- memset(&nd_mappings, 0, sizeof(nd_mappings));
- memset(&ndbr_desc, 0, sizeof(ndbr_desc));
- res.start = spa->address;
- res.end = res.start + spa->length - 1;
- ndr_desc = &ndbr_desc.ndr_desc;
- ndr_desc->res = &res;
- ndr_desc->provider_data = nfit_spa;
- ndr_desc->attr_groups = acpi_nfit_region_attribute_groups;
- if (spa->flags & ACPI_NFIT_PROXIMITY_VALID)
- ndr_desc->numa_node = acpi_map_pxm_to_online_node(
- spa->proximity_domain);
- else
- ndr_desc->numa_node = NUMA_NO_NODE;
-
- list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
- struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev;
- struct nd_mapping *nd_mapping;
-
- if (memdev->range_index != spa->range_index)
- continue;
- if (count >= ND_MAX_MAPPINGS) {
- dev_err(acpi_desc->dev, "spa%d exceeds max mappings %d\n",
- spa->range_index, ND_MAX_MAPPINGS);
- return -ENXIO;
- }
- nd_mapping = &nd_mappings[count++];
- rc = acpi_nfit_init_mapping(acpi_desc, nd_mapping, ndr_desc,
- memdev, nfit_spa);
- if (rc)
- goto out;
- }
-
- ndr_desc->nd_mapping = nd_mappings;
- ndr_desc->num_mappings = count;
- rc = acpi_nfit_init_interleave_set(acpi_desc, ndr_desc, spa);
- if (rc)
- goto out;
-
- nvdimm_bus = acpi_desc->nvdimm_bus;
- if (nfit_spa_type(spa) == NFIT_SPA_PM) {
- rc = acpi_nfit_insert_resource(acpi_desc, ndr_desc);
- if (rc) {
- dev_warn(acpi_desc->dev,
- "failed to insert pmem resource to iomem: %d\n",
- rc);
- goto out;
- }
-
- nfit_spa->nd_region = nvdimm_pmem_region_create(nvdimm_bus,
- ndr_desc);
- if (!nfit_spa->nd_region)
- rc = -ENOMEM;
- } else if (nfit_spa_type(spa) == NFIT_SPA_VOLATILE) {
- nfit_spa->nd_region = nvdimm_volatile_region_create(nvdimm_bus,
- ndr_desc);
- if (!nfit_spa->nd_region)
- rc = -ENOMEM;
- }
-
- out:
- if (rc)
- dev_err(acpi_desc->dev, "failed to register spa range %d\n",
- nfit_spa->spa->range_index);
- return rc;
-}
-
-static int ars_status_alloc(struct acpi_nfit_desc *acpi_desc,
- u32 max_ars)
-{
- struct device *dev = acpi_desc->dev;
- struct nd_cmd_ars_status *ars_status;
-
- if (acpi_desc->ars_status && acpi_desc->ars_status_size >= max_ars) {
- memset(acpi_desc->ars_status, 0, acpi_desc->ars_status_size);
- return 0;
- }
-
- if (acpi_desc->ars_status)
- devm_kfree(dev, acpi_desc->ars_status);
- acpi_desc->ars_status = NULL;
- ars_status = devm_kzalloc(dev, max_ars, GFP_KERNEL);
- if (!ars_status)
- return -ENOMEM;
- acpi_desc->ars_status = ars_status;
- acpi_desc->ars_status_size = max_ars;
- return 0;
-}
-
-static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc,
- struct nfit_spa *nfit_spa)
-{
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
- int rc;
-
- if (!nfit_spa->max_ars) {
- struct nd_cmd_ars_cap ars_cap;
-
- memset(&ars_cap, 0, sizeof(ars_cap));
- rc = ars_get_cap(acpi_desc, &ars_cap, nfit_spa);
- if (rc < 0)
- return rc;
- nfit_spa->max_ars = ars_cap.max_ars_out;
- nfit_spa->clear_err_unit = ars_cap.clear_err_unit;
- /* check that the supported scrub types match the spa type */
- if (nfit_spa_type(spa) == NFIT_SPA_VOLATILE &&
- ((ars_cap.status >> 16) & ND_ARS_VOLATILE) == 0)
- return -ENOTTY;
- else if (nfit_spa_type(spa) == NFIT_SPA_PM &&
- ((ars_cap.status >> 16) & ND_ARS_PERSISTENT) == 0)
- return -ENOTTY;
- }
-
- if (ars_status_alloc(acpi_desc, nfit_spa->max_ars))
- return -ENOMEM;
-
- rc = ars_get_status(acpi_desc);
- if (rc < 0 && rc != -ENOSPC)
- return rc;
-
- if (ars_status_process_records(acpi_desc->nvdimm_bus,
- acpi_desc->ars_status))
- return -ENOMEM;
-
- return 0;
-}
-
-static void acpi_nfit_async_scrub(struct acpi_nfit_desc *acpi_desc,
- struct nfit_spa *nfit_spa)
-{
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
- unsigned int overflow_retry = scrub_overflow_abort;
- u64 init_ars_start = 0, init_ars_len = 0;
- struct device *dev = acpi_desc->dev;
- unsigned int tmo = scrub_timeout;
- int rc;
-
- if (nfit_spa->ars_done || !nfit_spa->nd_region)
- return;
-
- rc = ars_start(acpi_desc, nfit_spa);
- /*
- * If we timed out the initial scan we'll still be busy here,
- * and will wait another timeout before giving up permanently.
- */
- if (rc < 0 && rc != -EBUSY)
- return;
-
- do {
- u64 ars_start, ars_len;
-
- if (acpi_desc->cancel)
- break;
- rc = acpi_nfit_query_poison(acpi_desc, nfit_spa);
- if (rc == -ENOTTY)
- break;
- if (rc == -EBUSY && !tmo) {
- dev_warn(dev, "range %d ars timeout, aborting\n",
- spa->range_index);
- break;
- }
-
- if (rc == -EBUSY) {
- /*
- * Note, entries may be appended to the list
- * while the lock is dropped, but the workqueue
- * being active prevents entries being deleted /
- * freed.
- */
- mutex_unlock(&acpi_desc->init_mutex);
- ssleep(1);
- tmo--;
- mutex_lock(&acpi_desc->init_mutex);
- continue;
- }
-
- /* we got some results, but there are more pending... */
- if (rc == -ENOSPC && overflow_retry--) {
- if (!init_ars_len) {
- init_ars_len = acpi_desc->ars_status->length;
- init_ars_start = acpi_desc->ars_status->address;
- }
- rc = ars_continue(acpi_desc);
- }
-
- if (rc < 0) {
- dev_warn(dev, "range %d ars continuation failed\n",
- spa->range_index);
- break;
- }
-
- if (init_ars_len) {
- ars_start = init_ars_start;
- ars_len = init_ars_len;
- } else {
- ars_start = acpi_desc->ars_status->address;
- ars_len = acpi_desc->ars_status->length;
- }
- dev_dbg(dev, "spa range: %d ars from %#llx + %#llx complete\n",
- spa->range_index, ars_start, ars_len);
- /* notify the region about new poison entries */
- nvdimm_region_notify(nfit_spa->nd_region,
- NVDIMM_REVALIDATE_POISON);
- break;
- } while (1);
-}
-
-static void acpi_nfit_scrub(struct work_struct *work)
-{
- struct device *dev;
- u64 init_scrub_length = 0;
- struct nfit_spa *nfit_spa;
- u64 init_scrub_address = 0;
- bool init_ars_done = false;
- struct acpi_nfit_desc *acpi_desc;
- unsigned int tmo = scrub_timeout;
- unsigned int overflow_retry = scrub_overflow_abort;
-
- acpi_desc = container_of(work, typeof(*acpi_desc), work);
- dev = acpi_desc->dev;
-
- /*
- * We scrub in 2 phases. The first phase waits for any platform
- * firmware initiated scrubs to complete and then we go search for the
- * affected spa regions to mark them scanned. In the second phase we
- * initiate a directed scrub for every range that was not scrubbed in
- * phase 1.
- */
-
- /* process platform firmware initiated scrubs */
- retry:
- mutex_lock(&acpi_desc->init_mutex);
- list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
- struct nd_cmd_ars_status *ars_status;
- struct acpi_nfit_system_address *spa;
- u64 ars_start, ars_len;
- int rc;
-
- if (acpi_desc->cancel)
- break;
-
- if (nfit_spa->nd_region)
- continue;
-
- if (init_ars_done) {
- /*
- * No need to re-query, we're now just
- * reconciling all the ranges covered by the
- * initial scrub
- */
- rc = 0;
- } else
- rc = acpi_nfit_query_poison(acpi_desc, nfit_spa);
-
- if (rc == -ENOTTY) {
- /* no ars capability, just register spa and move on */
- acpi_nfit_register_region(acpi_desc, nfit_spa);
- continue;
- }
-
- if (rc == -EBUSY && !tmo) {
- /* fallthrough to directed scrub in phase 2 */
- dev_warn(dev, "timeout awaiting ars results, continuing...\n");
- break;
- } else if (rc == -EBUSY) {
- mutex_unlock(&acpi_desc->init_mutex);
- ssleep(1);
- tmo--;
- goto retry;
- }
-
- /* we got some results, but there are more pending... */
- if (rc == -ENOSPC && overflow_retry--) {
- ars_status = acpi_desc->ars_status;
- /*
- * Record the original scrub range, so that we
- * can recall all the ranges impacted by the
- * initial scrub.
- */
- if (!init_scrub_length) {
- init_scrub_length = ars_status->length;
- init_scrub_address = ars_status->address;
- }
- rc = ars_continue(acpi_desc);
- if (rc == 0) {
- mutex_unlock(&acpi_desc->init_mutex);
- goto retry;
- }
- }
-
- if (rc < 0) {
- /*
- * Initial scrub failed, we'll give it one more
- * try below...
- */
- break;
- }
-
- /* We got some final results, record completed ranges */
- ars_status = acpi_desc->ars_status;
- if (init_scrub_length) {
- ars_start = init_scrub_address;
- ars_len = ars_start + init_scrub_length;
- } else {
- ars_start = ars_status->address;
- ars_len = ars_status->length;
- }
- spa = nfit_spa->spa;
-
- if (!init_ars_done) {
- init_ars_done = true;
- dev_dbg(dev, "init scrub %#llx + %#llx complete\n",
- ars_start, ars_len);
- }
- if (ars_start <= spa->address && ars_start + ars_len
- >= spa->address + spa->length)
- acpi_nfit_register_region(acpi_desc, nfit_spa);
- }
-
- /*
- * For all the ranges not covered by an initial scrub we still
- * want to see if there are errors, but it's ok to discover them
- * asynchronously.
- */
- list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
- /*
- * Flag all the ranges that still need scrubbing, but
- * register them now to make data available.
- */
- if (nfit_spa->nd_region)
- nfit_spa->ars_done = 1;
- else
- acpi_nfit_register_region(acpi_desc, nfit_spa);
- }
-
- list_for_each_entry(nfit_spa, &acpi_desc->spas, list)
- acpi_nfit_async_scrub(acpi_desc, nfit_spa);
- mutex_unlock(&acpi_desc->init_mutex);
-}
-
-static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc)
-{
- struct nfit_spa *nfit_spa;
- int rc;
-
- list_for_each_entry(nfit_spa, &acpi_desc->spas, list)
- if (nfit_spa_type(nfit_spa->spa) == NFIT_SPA_DCR) {
- /* BLK regions don't need to wait for ars results */
- rc = acpi_nfit_register_region(acpi_desc, nfit_spa);
- if (rc)
- return rc;
- }
-
- queue_work(nfit_wq, &acpi_desc->work);
- return 0;
-}
-
-static int acpi_nfit_check_deletions(struct acpi_nfit_desc *acpi_desc,
- struct nfit_table_prev *prev)
-{
- struct device *dev = acpi_desc->dev;
-
- if (!list_empty(&prev->spas) ||
- !list_empty(&prev->memdevs) ||
- !list_empty(&prev->dcrs) ||
- !list_empty(&prev->bdws) ||
- !list_empty(&prev->idts) ||
- !list_empty(&prev->flushes)) {
- dev_err(dev, "new nfit deletes entries (unsupported)\n");
- return -ENXIO;
- }
- return 0;
-}
-
-int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz)
-{
- struct device *dev = acpi_desc->dev;
- struct nfit_table_prev prev;
- const void *end;
- u8 *data;
- int rc;
-
- mutex_lock(&acpi_desc->init_mutex);
-
- INIT_LIST_HEAD(&prev.spas);
- INIT_LIST_HEAD(&prev.memdevs);
- INIT_LIST_HEAD(&prev.dcrs);
- INIT_LIST_HEAD(&prev.bdws);
- INIT_LIST_HEAD(&prev.idts);
- INIT_LIST_HEAD(&prev.flushes);
-
- list_cut_position(&prev.spas, &acpi_desc->spas,
- acpi_desc->spas.prev);
- list_cut_position(&prev.memdevs, &acpi_desc->memdevs,
- acpi_desc->memdevs.prev);
- list_cut_position(&prev.dcrs, &acpi_desc->dcrs,
- acpi_desc->dcrs.prev);
- list_cut_position(&prev.bdws, &acpi_desc->bdws,
- acpi_desc->bdws.prev);
- list_cut_position(&prev.idts, &acpi_desc->idts,
- acpi_desc->idts.prev);
- list_cut_position(&prev.flushes, &acpi_desc->flushes,
- acpi_desc->flushes.prev);
-
- data = (u8 *) acpi_desc->nfit;
- end = data + sz;
- while (!IS_ERR_OR_NULL(data))
- data = add_table(acpi_desc, &prev, data, end);
-
- if (IS_ERR(data)) {
- dev_dbg(dev, "%s: nfit table parsing error: %ld\n", __func__,
- PTR_ERR(data));
- rc = PTR_ERR(data);
- goto out_unlock;
- }
-
- rc = acpi_nfit_check_deletions(acpi_desc, &prev);
- if (rc)
- goto out_unlock;
-
- if (nfit_mem_init(acpi_desc) != 0) {
- rc = -ENOMEM;
- goto out_unlock;
- }
-
- acpi_nfit_init_dsms(acpi_desc);
-
- rc = acpi_nfit_register_dimms(acpi_desc);
- if (rc)
- goto out_unlock;
-
- rc = acpi_nfit_register_regions(acpi_desc);
-
- out_unlock:
- mutex_unlock(&acpi_desc->init_mutex);
- return rc;
-}
-EXPORT_SYMBOL_GPL(acpi_nfit_init);
-
-struct acpi_nfit_flush_work {
- struct work_struct work;
- struct completion cmp;
-};
-
-static void flush_probe(struct work_struct *work)
-{
- struct acpi_nfit_flush_work *flush;
-
- flush = container_of(work, typeof(*flush), work);
- complete(&flush->cmp);
-}
-
-static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
-{
- struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
- struct device *dev = acpi_desc->dev;
- struct acpi_nfit_flush_work flush;
-
- /* bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
- device_lock(dev);
- device_unlock(dev);
-
- /*
- * Scrub work could take 10s of seconds, userspace may give up so we
- * need to be interruptible while waiting.
- */
- INIT_WORK_ONSTACK(&flush.work, flush_probe);
- COMPLETION_INITIALIZER_ONSTACK(flush.cmp);
- queue_work(nfit_wq, &flush.work);
- return wait_for_completion_interruptible(&flush.cmp);
-}
-
-static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
- struct nvdimm *nvdimm, unsigned int cmd)
-{
- struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
-
- if (nvdimm)
- return 0;
- if (cmd != ND_CMD_ARS_START)
- return 0;
-
- /*
- * The kernel and userspace may race to initiate a scrub, but
- * the scrub thread is prepared to lose that initial race. It
- * just needs guarantees that any ars it initiates are not
- * interrupted by any intervening start reqeusts from userspace.
- */
- if (work_busy(&acpi_desc->work))
- return -EBUSY;
-
- return 0;
-}
-
-void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev)
-{
- struct nvdimm_bus_descriptor *nd_desc;
-
- dev_set_drvdata(dev, acpi_desc);
- acpi_desc->dev = dev;
- acpi_desc->blk_do_io = acpi_nfit_blk_region_do_io;
- nd_desc = &acpi_desc->nd_desc;
- nd_desc->provider_name = "ACPI.NFIT";
- nd_desc->ndctl = acpi_nfit_ctl;
- nd_desc->flush_probe = acpi_nfit_flush_probe;
- nd_desc->clear_to_send = acpi_nfit_clear_to_send;
- nd_desc->attr_groups = acpi_nfit_attribute_groups;
-
- INIT_LIST_HEAD(&acpi_desc->spa_maps);
- INIT_LIST_HEAD(&acpi_desc->spas);
- INIT_LIST_HEAD(&acpi_desc->dcrs);
- INIT_LIST_HEAD(&acpi_desc->bdws);
- INIT_LIST_HEAD(&acpi_desc->idts);
- INIT_LIST_HEAD(&acpi_desc->flushes);
- INIT_LIST_HEAD(&acpi_desc->memdevs);
- INIT_LIST_HEAD(&acpi_desc->dimms);
- mutex_init(&acpi_desc->spa_map_mutex);
- mutex_init(&acpi_desc->init_mutex);
- INIT_WORK(&acpi_desc->work, acpi_nfit_scrub);
-}
-EXPORT_SYMBOL_GPL(acpi_nfit_desc_init);
-
-static int acpi_nfit_add(struct acpi_device *adev)
-{
- struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_nfit_desc *acpi_desc;
- struct device *dev = &adev->dev;
- struct acpi_table_header *tbl;
- acpi_status status = AE_OK;
- acpi_size sz;
- int rc;
-
- status = acpi_get_table_with_size(ACPI_SIG_NFIT, 0, &tbl, &sz);
- if (ACPI_FAILURE(status)) {
- /* This is ok, we could have an nvdimm hotplugged later */
- dev_dbg(dev, "failed to find NFIT at startup\n");
- return 0;
- }
-
- acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);
- if (!acpi_desc)
- return -ENOMEM;
- acpi_nfit_desc_init(acpi_desc, &adev->dev);
- acpi_desc->nvdimm_bus = nvdimm_bus_register(dev, &acpi_desc->nd_desc);
- if (!acpi_desc->nvdimm_bus)
- return -ENOMEM;
-
- /*
- * Save the acpi header for later and then skip it,
- * making nfit point to the first nfit table header.
- */
- acpi_desc->acpi_header = *tbl;
- acpi_desc->nfit = (void *) tbl + sizeof(struct acpi_table_nfit);
- sz -= sizeof(struct acpi_table_nfit);
-
- /* Evaluate _FIT and override with that if present */
- status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf);
- if (ACPI_SUCCESS(status) && buf.length > 0) {
- union acpi_object *obj;
- /*
- * Adjust for the acpi_object header of the _FIT
- */
- obj = buf.pointer;
- if (obj->type == ACPI_TYPE_BUFFER) {
- acpi_desc->nfit =
- (struct acpi_nfit_header *)obj->buffer.pointer;
- sz = obj->buffer.length;
- } else
- dev_dbg(dev, "%s invalid type %d, ignoring _FIT\n",
- __func__, (int) obj->type);
- }
-
- rc = acpi_nfit_init(acpi_desc, sz);
- if (rc) {
- nvdimm_bus_unregister(acpi_desc->nvdimm_bus);
- return rc;
- }
- return 0;
-}
-
-static int acpi_nfit_remove(struct acpi_device *adev)
-{
- struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(&adev->dev);
-
- acpi_desc->cancel = 1;
- flush_workqueue(nfit_wq);
- nvdimm_bus_unregister(acpi_desc->nvdimm_bus);
- return 0;
-}
-
-static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
-{
- struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(&adev->dev);
- struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_nfit_header *nfit_saved;
- union acpi_object *obj;
- struct device *dev = &adev->dev;
- acpi_status status;
- int ret;
-
- dev_dbg(dev, "%s: event: %d\n", __func__, event);
-
- device_lock(dev);
- if (!dev->driver) {
- /* dev->driver may be null if we're being removed */
- dev_dbg(dev, "%s: no driver found for dev\n", __func__);
- goto out_unlock;
- }
-
- if (!acpi_desc) {
- acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);
- if (!acpi_desc)
- goto out_unlock;
- acpi_nfit_desc_init(acpi_desc, &adev->dev);
- acpi_desc->nvdimm_bus = nvdimm_bus_register(dev, &acpi_desc->nd_desc);
- if (!acpi_desc->nvdimm_bus)
- goto out_unlock;
- } else {
- /*
- * Finish previous registration before considering new
- * regions.
- */
- flush_workqueue(nfit_wq);
- }
-
- /* Evaluate _FIT */
- status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf);
- if (ACPI_FAILURE(status)) {
- dev_err(dev, "failed to evaluate _FIT\n");
- goto out_unlock;
- }
-
- nfit_saved = acpi_desc->nfit;
- obj = buf.pointer;
- if (obj->type == ACPI_TYPE_BUFFER) {
- acpi_desc->nfit =
- (struct acpi_nfit_header *)obj->buffer.pointer;
- ret = acpi_nfit_init(acpi_desc, obj->buffer.length);
- if (ret) {
- /* Merge failed, restore old nfit, and exit */
- acpi_desc->nfit = nfit_saved;
- dev_err(dev, "failed to merge updated NFIT\n");
- }
- } else {
- /* Bad _FIT, restore old nfit */
- dev_err(dev, "Invalid _FIT\n");
- }
- kfree(buf.pointer);
-
- out_unlock:
- device_unlock(dev);
-}
-
-static const struct acpi_device_id acpi_nfit_ids[] = {
- { "ACPI0012", 0 },
- { "", 0 },
-};
-MODULE_DEVICE_TABLE(acpi, acpi_nfit_ids);
-
-static struct acpi_driver acpi_nfit_driver = {
- .name = KBUILD_MODNAME,
- .ids = acpi_nfit_ids,
- .ops = {
- .add = acpi_nfit_add,
- .remove = acpi_nfit_remove,
- .notify = acpi_nfit_notify,
- },
-};
-
-static __init int nfit_init(void)
-{
- BUILD_BUG_ON(sizeof(struct acpi_table_nfit) != 40);
- BUILD_BUG_ON(sizeof(struct acpi_nfit_system_address) != 56);
- BUILD_BUG_ON(sizeof(struct acpi_nfit_memory_map) != 48);
- BUILD_BUG_ON(sizeof(struct acpi_nfit_interleave) != 20);
- BUILD_BUG_ON(sizeof(struct acpi_nfit_smbios) != 9);
- BUILD_BUG_ON(sizeof(struct acpi_nfit_control_region) != 80);
- BUILD_BUG_ON(sizeof(struct acpi_nfit_data_region) != 40);
-
- acpi_str_to_uuid(UUID_VOLATILE_MEMORY, nfit_uuid[NFIT_SPA_VOLATILE]);
- acpi_str_to_uuid(UUID_PERSISTENT_MEMORY, nfit_uuid[NFIT_SPA_PM]);
- acpi_str_to_uuid(UUID_CONTROL_REGION, nfit_uuid[NFIT_SPA_DCR]);
- acpi_str_to_uuid(UUID_DATA_REGION, nfit_uuid[NFIT_SPA_BDW]);
- acpi_str_to_uuid(UUID_VOLATILE_VIRTUAL_DISK, nfit_uuid[NFIT_SPA_VDISK]);
- acpi_str_to_uuid(UUID_VOLATILE_VIRTUAL_CD, nfit_uuid[NFIT_SPA_VCD]);
- acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_DISK, nfit_uuid[NFIT_SPA_PDISK]);
- acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_CD, nfit_uuid[NFIT_SPA_PCD]);
- acpi_str_to_uuid(UUID_NFIT_BUS, nfit_uuid[NFIT_DEV_BUS]);
- acpi_str_to_uuid(UUID_NFIT_DIMM, nfit_uuid[NFIT_DEV_DIMM]);
- acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE1, nfit_uuid[NFIT_DEV_DIMM_N_HPE1]);
- acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE2, nfit_uuid[NFIT_DEV_DIMM_N_HPE2]);
-
- nfit_wq = create_singlethread_workqueue("nfit");
- if (!nfit_wq)
- return -ENOMEM;
-
- return acpi_bus_register_driver(&acpi_nfit_driver);
-}
-
-static __exit void nfit_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_nfit_driver);
- destroy_workqueue(nfit_wq);
-}
-
-module_init(nfit_init);
-module_exit(nfit_exit);
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h
deleted file mode 100644
index 02b9ea1e8..000000000
--- a/drivers/acpi/nfit.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * NVDIMM Firmware Interface Table - NFIT
- *
- * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-#ifndef __NFIT_H__
-#define __NFIT_H__
-#include <linux/workqueue.h>
-#include <linux/libnvdimm.h>
-#include <linux/types.h>
-#include <linux/uuid.h>
-#include <linux/acpi.h>
-#include <acpi/acuuid.h>
-
-/* ACPI 6.1 */
-#define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba"
-
-/* http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf */
-#define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66"
-
-/* https://github.com/HewlettPackard/hpe-nvm/blob/master/Documentation/ */
-#define UUID_NFIT_DIMM_N_HPE1 "9002c334-acf3-4c0e-9642-a235f0d53bc6"
-#define UUID_NFIT_DIMM_N_HPE2 "5008664b-b758-41a0-a03c-27c2f2d04f7e"
-
-#define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
- | ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
- | ACPI_NFIT_MEM_NOT_ARMED)
-
-enum nfit_uuids {
- /* for simplicity alias the uuid index with the family id */
- NFIT_DEV_DIMM = NVDIMM_FAMILY_INTEL,
- NFIT_DEV_DIMM_N_HPE1 = NVDIMM_FAMILY_HPE1,
- NFIT_DEV_DIMM_N_HPE2 = NVDIMM_FAMILY_HPE2,
- NFIT_SPA_VOLATILE,
- NFIT_SPA_PM,
- NFIT_SPA_DCR,
- NFIT_SPA_BDW,
- NFIT_SPA_VDISK,
- NFIT_SPA_VCD,
- NFIT_SPA_PDISK,
- NFIT_SPA_PCD,
- NFIT_DEV_BUS,
- NFIT_UUID_MAX,
-};
-
-/*
- * Region format interface codes are stored with the interface as the
- * LSB and the function as the MSB.
- */
-#define NFIT_FIC_BYTE cpu_to_le16(0x101) /* byte-addressable energy backed */
-#define NFIT_FIC_BLK cpu_to_le16(0x201) /* block-addressable non-energy backed */
-#define NFIT_FIC_BYTEN cpu_to_le16(0x301) /* byte-addressable non-energy backed */
-
-enum {
- NFIT_BLK_READ_FLUSH = 1,
- NFIT_BLK_DCR_LATCH = 2,
- NFIT_ARS_STATUS_DONE = 0,
- NFIT_ARS_STATUS_BUSY = 1 << 16,
- NFIT_ARS_STATUS_NONE = 2 << 16,
- NFIT_ARS_STATUS_INTR = 3 << 16,
- NFIT_ARS_START_BUSY = 6,
- NFIT_ARS_CAP_NONE = 1,
- NFIT_ARS_F_OVERFLOW = 1,
- NFIT_ARS_TIMEOUT = 90,
-};
-
-struct nfit_spa {
- struct acpi_nfit_system_address *spa;
- struct list_head list;
- struct nd_region *nd_region;
- unsigned int ars_done:1;
- u32 clear_err_unit;
- u32 max_ars;
-};
-
-struct nfit_dcr {
- struct acpi_nfit_control_region *dcr;
- struct list_head list;
-};
-
-struct nfit_bdw {
- struct acpi_nfit_data_region *bdw;
- struct list_head list;
-};
-
-struct nfit_idt {
- struct acpi_nfit_interleave *idt;
- struct list_head list;
-};
-
-struct nfit_flush {
- struct acpi_nfit_flush_address *flush;
- struct list_head list;
-};
-
-struct nfit_memdev {
- struct acpi_nfit_memory_map *memdev;
- struct list_head list;
-};
-
-/* assembled tables for a given dimm/memory-device */
-struct nfit_mem {
- struct nvdimm *nvdimm;
- struct acpi_nfit_memory_map *memdev_dcr;
- struct acpi_nfit_memory_map *memdev_pmem;
- struct acpi_nfit_memory_map *memdev_bdw;
- struct acpi_nfit_control_region *dcr;
- struct acpi_nfit_data_region *bdw;
- struct acpi_nfit_system_address *spa_dcr;
- struct acpi_nfit_system_address *spa_bdw;
- struct acpi_nfit_interleave *idt_dcr;
- struct acpi_nfit_interleave *idt_bdw;
- struct nfit_flush *nfit_flush;
- struct list_head list;
- struct acpi_device *adev;
- struct acpi_nfit_desc *acpi_desc;
- unsigned long dsm_mask;
- int family;
-};
-
-struct acpi_nfit_desc {
- struct nvdimm_bus_descriptor nd_desc;
- struct acpi_table_header acpi_header;
- struct acpi_nfit_header *nfit;
- struct mutex spa_map_mutex;
- struct mutex init_mutex;
- struct list_head spa_maps;
- struct list_head memdevs;
- struct list_head flushes;
- struct list_head dimms;
- struct list_head spas;
- struct list_head dcrs;
- struct list_head bdws;
- struct list_head idts;
- struct nvdimm_bus *nvdimm_bus;
- struct device *dev;
- struct nd_cmd_ars_status *ars_status;
- size_t ars_status_size;
- struct work_struct work;
- unsigned int cancel:1;
- unsigned long dimm_cmd_force_en;
- unsigned long bus_cmd_force_en;
- int (*blk_do_io)(struct nd_blk_region *ndbr, resource_size_t dpa,
- void *iobuf, u64 len, int rw);
-};
-
-enum nd_blk_mmio_selector {
- BDW,
- DCR,
-};
-
-struct nd_blk_addr {
- union {
- void __iomem *base;
- void __pmem *aperture;
- };
-};
-
-struct nfit_blk {
- struct nfit_blk_mmio {
- struct nd_blk_addr addr;
- u64 size;
- u64 base_offset;
- u32 line_size;
- u32 num_lines;
- u32 table_size;
- struct acpi_nfit_interleave *idt;
- struct acpi_nfit_system_address *spa;
- } mmio[2];
- struct nd_region *nd_region;
- u64 bdw_offset; /* post interleave offset */
- u64 stat_offset;
- u64 cmd_offset;
- void __iomem *nvdimm_flush;
- u32 dimm_flags;
-};
-
-enum spa_map_type {
- SPA_MAP_CONTROL,
- SPA_MAP_APERTURE,
-};
-
-struct nfit_spa_mapping {
- struct acpi_nfit_desc *acpi_desc;
- struct acpi_nfit_system_address *spa;
- struct list_head list;
- struct kref kref;
- enum spa_map_type type;
- struct nd_blk_addr addr;
-};
-
-static inline struct nfit_spa_mapping *to_spa_map(struct kref *kref)
-{
- return container_of(kref, struct nfit_spa_mapping, kref);
-}
-
-static inline struct acpi_nfit_memory_map *__to_nfit_memdev(
- struct nfit_mem *nfit_mem)
-{
- if (nfit_mem->memdev_dcr)
- return nfit_mem->memdev_dcr;
- return nfit_mem->memdev_pmem;
-}
-
-static inline struct acpi_nfit_desc *to_acpi_desc(
- struct nvdimm_bus_descriptor *nd_desc)
-{
- return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
-}
-
-const u8 *to_nfit_uuid(enum nfit_uuids id);
-int acpi_nfit_init(struct acpi_nfit_desc *nfit, acpi_size sz);
-void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev);
-#endif /* __NFIT_H__ */
diff --git a/drivers/ata/ahci_brcmstb.c b/drivers/ata/ahci_brcmstb.c
deleted file mode 100644
index e87bcec0f..000000000
--- a/drivers/ata/ahci_brcmstb.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Broadcom SATA3 AHCI Controller Driver
- *
- * Copyright © 2009-2015 Broadcom Corporation
- *
- * 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, 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 <linux/ahci_platform.h>
-#include <linux/compiler.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/libata.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/string.h>
-
-#include "ahci.h"
-
-#define DRV_NAME "brcm-ahci"
-
-#define SATA_TOP_CTRL_VERSION 0x0
-#define SATA_TOP_CTRL_BUS_CTRL 0x4
- #define MMIO_ENDIAN_SHIFT 0 /* CPU->AHCI */
- #define DMADESC_ENDIAN_SHIFT 2 /* AHCI->DDR */
- #define DMADATA_ENDIAN_SHIFT 4 /* AHCI->DDR */
- #define PIODATA_ENDIAN_SHIFT 6
- #define ENDIAN_SWAP_NONE 0
- #define ENDIAN_SWAP_FULL 2
- #define OVERRIDE_HWINIT BIT(16)
-#define SATA_TOP_CTRL_TP_CTRL 0x8
-#define SATA_TOP_CTRL_PHY_CTRL 0xc
- #define SATA_TOP_CTRL_PHY_CTRL_1 0x0
- #define SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE BIT(14)
- #define SATA_TOP_CTRL_PHY_CTRL_2 0x4
- #define SATA_TOP_CTRL_2_SW_RST_MDIOREG BIT(0)
- #define SATA_TOP_CTRL_2_SW_RST_OOB BIT(1)
- #define SATA_TOP_CTRL_2_SW_RST_RX BIT(2)
- #define SATA_TOP_CTRL_2_SW_RST_TX BIT(3)
- #define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET BIT(14)
- #define SATA_TOP_CTRL_PHY_OFFS 0x8
- #define SATA_TOP_MAX_PHYS 2
-
-#define SATA_FIRST_PORT_CTRL 0x700
-#define SATA_NEXT_PORT_CTRL_OFFSET 0x80
-#define SATA_PORT_PCTRL6(reg_base) (reg_base + 0x18)
-
-/* On big-endian MIPS, buses are reversed to big endian, so switch them back */
-#if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN)
-#define DATA_ENDIAN 2 /* AHCI->DDR inbound accesses */
-#define MMIO_ENDIAN 2 /* CPU->AHCI outbound accesses */
-#else
-#define DATA_ENDIAN 0
-#define MMIO_ENDIAN 0
-#endif
-
-#define BUS_CTRL_ENDIAN_CONF \
- ((DATA_ENDIAN << DMADATA_ENDIAN_SHIFT) | \
- (DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) | \
- (MMIO_ENDIAN << MMIO_ENDIAN_SHIFT))
-
-enum brcm_ahci_quirks {
- BRCM_AHCI_QUIRK_NO_NCQ = BIT(0),
- BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1),
-};
-
-struct brcm_ahci_priv {
- struct device *dev;
- void __iomem *top_ctrl;
- u32 port_mask;
- u32 quirks;
-};
-
-static const struct ata_port_info ahci_brcm_port_info = {
- .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
- .link_flags = ATA_LFLAG_NO_DB_DELAY,
- .pio_mask = ATA_PIO4,
- .udma_mask = ATA_UDMA6,
- .port_ops = &ahci_platform_ops,
-};
-
-static inline u32 brcm_sata_readreg(void __iomem *addr)
-{
- /*
- * MIPS endianness is configured by boot strap, which also reverses all
- * bus endianness (i.e., big-endian CPU + big endian bus ==> native
- * endian I/O).
- *
- * Other architectures (e.g., ARM) either do not support big endian, or
- * else leave I/O in little endian mode.
- */
- if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
- return __raw_readl(addr);
- else
- return readl_relaxed(addr);
-}
-
-static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
-{
- /* See brcm_sata_readreg() comments */
- if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
- __raw_writel(val, addr);
- else
- writel_relaxed(val, addr);
-}
-
-static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv)
-{
- struct brcm_ahci_priv *priv = hpriv->plat_data;
- u32 bus_ctrl, port_ctrl, host_caps;
- int i;
-
- /* Enable support for ALPM */
- bus_ctrl = brcm_sata_readreg(priv->top_ctrl +
- SATA_TOP_CTRL_BUS_CTRL);
- brcm_sata_writereg(bus_ctrl | OVERRIDE_HWINIT,
- priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
- host_caps = readl(hpriv->mmio + HOST_CAP);
- writel(host_caps | HOST_CAP_ALPM, hpriv->mmio);
- brcm_sata_writereg(bus_ctrl, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
-
- /*
- * Adjust timeout to allow PLL sufficient time to lock while waking
- * up from slumber mode.
- */
- for (i = 0, port_ctrl = SATA_FIRST_PORT_CTRL;
- i < SATA_TOP_MAX_PHYS;
- i++, port_ctrl += SATA_NEXT_PORT_CTRL_OFFSET) {
- if (priv->port_mask & BIT(i))
- writel(0xff1003fc,
- hpriv->mmio + SATA_PORT_PCTRL6(port_ctrl));
- }
-}
-
-static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port)
-{
- void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
- (port * SATA_TOP_CTRL_PHY_OFFS);
- void __iomem *p;
- u32 reg;
-
- if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
- return;
-
- /* clear PHY_DEFAULT_POWER_STATE */
- p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
- reg = brcm_sata_readreg(p);
- reg &= ~SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
- brcm_sata_writereg(reg, p);
-
- /* reset the PHY digital logic */
- p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
- reg = brcm_sata_readreg(p);
- reg &= ~(SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
- SATA_TOP_CTRL_2_SW_RST_RX);
- reg |= SATA_TOP_CTRL_2_SW_RST_TX;
- brcm_sata_writereg(reg, p);
- reg = brcm_sata_readreg(p);
- reg |= SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
- brcm_sata_writereg(reg, p);
- reg = brcm_sata_readreg(p);
- reg &= ~SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
- brcm_sata_writereg(reg, p);
- (void)brcm_sata_readreg(p);
-}
-
-static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port)
-{
- void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
- (port * SATA_TOP_CTRL_PHY_OFFS);
- void __iomem *p;
- u32 reg;
-
- if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
- return;
-
- /* power-off the PHY digital logic */
- p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
- reg = brcm_sata_readreg(p);
- reg |= (SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
- SATA_TOP_CTRL_2_SW_RST_RX | SATA_TOP_CTRL_2_SW_RST_TX |
- SATA_TOP_CTRL_2_PHY_GLOBAL_RESET);
- brcm_sata_writereg(reg, p);
-
- /* set PHY_DEFAULT_POWER_STATE */
- p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
- reg = brcm_sata_readreg(p);
- reg |= SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
- brcm_sata_writereg(reg, p);
-}
-
-static void brcm_sata_phys_enable(struct brcm_ahci_priv *priv)
-{
- int i;
-
- for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
- if (priv->port_mask & BIT(i))
- brcm_sata_phy_enable(priv, i);
-}
-
-static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv)
-{
- int i;
-
- for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
- if (priv->port_mask & BIT(i))
- brcm_sata_phy_disable(priv, i);
-}
-
-static u32 brcm_ahci_get_portmask(struct platform_device *pdev,
- struct brcm_ahci_priv *priv)
-{
- void __iomem *ahci;
- struct resource *res;
- u32 impl;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci");
- ahci = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(ahci))
- return 0;
-
- impl = readl(ahci + HOST_PORTS_IMPL);
-
- if (fls(impl) > SATA_TOP_MAX_PHYS)
- dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n",
- impl);
- else if (!impl)
- dev_info(priv->dev, "no ports found\n");
-
- devm_iounmap(&pdev->dev, ahci);
- devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
-
- return impl;
-}
-
-static void brcm_sata_init(struct brcm_ahci_priv *priv)
-{
- /* Configure endianness */
- brcm_sata_writereg(BUS_CTRL_ENDIAN_CONF,
- priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int brcm_ahci_suspend(struct device *dev)
-{
- struct ata_host *host = dev_get_drvdata(dev);
- struct ahci_host_priv *hpriv = host->private_data;
- struct brcm_ahci_priv *priv = hpriv->plat_data;
- int ret;
-
- ret = ahci_platform_suspend(dev);
- brcm_sata_phys_disable(priv);
- return ret;
-}
-
-static int brcm_ahci_resume(struct device *dev)
-{
- struct ata_host *host = dev_get_drvdata(dev);
- struct ahci_host_priv *hpriv = host->private_data;
- struct brcm_ahci_priv *priv = hpriv->plat_data;
-
- brcm_sata_init(priv);
- brcm_sata_phys_enable(priv);
- brcm_sata_alpm_init(hpriv);
- return ahci_platform_resume(dev);
-}
-#endif
-
-static struct scsi_host_template ahci_platform_sht = {
- AHCI_SHT(DRV_NAME),
-};
-
-static int brcm_ahci_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct brcm_ahci_priv *priv;
- struct ahci_host_priv *hpriv;
- struct resource *res;
- int ret;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- priv->dev = dev;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-ctrl");
- priv->top_ctrl = devm_ioremap_resource(dev, res);
- if (IS_ERR(priv->top_ctrl))
- return PTR_ERR(priv->top_ctrl);
-
- if (of_device_is_compatible(dev->of_node, "brcm,bcm7425-ahci")) {
- priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ;
- priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
- }
-
- brcm_sata_init(priv);
-
- priv->port_mask = brcm_ahci_get_portmask(pdev, priv);
- if (!priv->port_mask)
- return -ENODEV;
-
- brcm_sata_phys_enable(priv);
-
- hpriv = ahci_platform_get_resources(pdev);
- if (IS_ERR(hpriv))
- return PTR_ERR(hpriv);
- hpriv->plat_data = priv;
- hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP;
-
- brcm_sata_alpm_init(hpriv);
-
- ret = ahci_platform_enable_resources(hpriv);
- if (ret)
- return ret;
-
- if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ)
- hpriv->flags |= AHCI_HFLAG_NO_NCQ;
-
- ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
- &ahci_platform_sht);
- if (ret)
- return ret;
-
- dev_info(dev, "Broadcom AHCI SATA3 registered\n");
-
- return 0;
-}
-
-static int brcm_ahci_remove(struct platform_device *pdev)
-{
- struct ata_host *host = dev_get_drvdata(&pdev->dev);
- struct ahci_host_priv *hpriv = host->private_data;
- struct brcm_ahci_priv *priv = hpriv->plat_data;
- int ret;
-
- ret = ata_platform_remove_one(pdev);
- if (ret)
- return ret;
-
- brcm_sata_phys_disable(priv);
-
- return 0;
-}
-
-static const struct of_device_id ahci_of_match[] = {
- {.compatible = "brcm,bcm7425-ahci"},
- {.compatible = "brcm,bcm7445-ahci"},
- {},
-};
-MODULE_DEVICE_TABLE(of, ahci_of_match);
-
-static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
-
-static struct platform_driver brcm_ahci_driver = {
- .probe = brcm_ahci_probe,
- .remove = brcm_ahci_remove,
- .driver = {
- .name = DRV_NAME,
- .of_match_table = ahci_of_match,
- .pm = &ahci_brcm_pm_ops,
- },
-};
-module_platform_driver(brcm_ahci_driver);
-
-MODULE_DESCRIPTION("Broadcom SATA3 AHCI Controller Driver");
-MODULE_AUTHOR("Brian Norris");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:sata-brcmstb");
diff --git a/drivers/block/zram/zcomp_lz4.c b/drivers/block/zram/zcomp_lz4.c
deleted file mode 100644
index 0110086ac..000000000
--- a/drivers/block/zram/zcomp_lz4.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2014 Sergey Senozhatsky.
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/lz4.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-
-#include "zcomp_lz4.h"
-
-static void *zcomp_lz4_create(gfp_t flags)
-{
- void *ret;
-
- ret = kmalloc(LZ4_MEM_COMPRESS, flags);
- if (!ret)
- ret = __vmalloc(LZ4_MEM_COMPRESS,
- flags | __GFP_HIGHMEM,
- PAGE_KERNEL);
- return ret;
-}
-
-static void zcomp_lz4_destroy(void *private)
-{
- kvfree(private);
-}
-
-static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,
- size_t *dst_len, void *private)
-{
- /* return : Success if return 0 */
- return lz4_compress(src, PAGE_SIZE, dst, dst_len, private);
-}
-
-static int zcomp_lz4_decompress(const unsigned char *src, size_t src_len,
- unsigned char *dst)
-{
- size_t dst_len = PAGE_SIZE;
- /* return : Success if return 0 */
- return lz4_decompress_unknownoutputsize(src, src_len, dst, &dst_len);
-}
-
-struct zcomp_backend zcomp_lz4 = {
- .compress = zcomp_lz4_compress,
- .decompress = zcomp_lz4_decompress,
- .create = zcomp_lz4_create,
- .destroy = zcomp_lz4_destroy,
- .name = "lz4",
-};
diff --git a/drivers/block/zram/zcomp_lz4.h b/drivers/block/zram/zcomp_lz4.h
deleted file mode 100644
index 60613fb29..000000000
--- a/drivers/block/zram/zcomp_lz4.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2014 Sergey Senozhatsky.
- *
- * 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.
- */
-
-#ifndef _ZCOMP_LZ4_H_
-#define _ZCOMP_LZ4_H_
-
-#include "zcomp.h"
-
-extern struct zcomp_backend zcomp_lz4;
-
-#endif /* _ZCOMP_LZ4_H_ */
diff --git a/drivers/block/zram/zcomp_lzo.c b/drivers/block/zram/zcomp_lzo.c
deleted file mode 100644
index ed7a1f054..000000000
--- a/drivers/block/zram/zcomp_lzo.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2014 Sergey Senozhatsky.
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/lzo.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-
-#include "zcomp_lzo.h"
-
-static void *lzo_create(gfp_t flags)
-{
- void *ret;
-
- ret = kmalloc(LZO1X_MEM_COMPRESS, flags);
- if (!ret)
- ret = __vmalloc(LZO1X_MEM_COMPRESS,
- flags | __GFP_HIGHMEM,
- PAGE_KERNEL);
- return ret;
-}
-
-static void lzo_destroy(void *private)
-{
- kvfree(private);
-}
-
-static int lzo_compress(const unsigned char *src, unsigned char *dst,
- size_t *dst_len, void *private)
-{
- int ret = lzo1x_1_compress(src, PAGE_SIZE, dst, dst_len, private);
- return ret == LZO_E_OK ? 0 : ret;
-}
-
-static int lzo_decompress(const unsigned char *src, size_t src_len,
- unsigned char *dst)
-{
- size_t dst_len = PAGE_SIZE;
- int ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
- return ret == LZO_E_OK ? 0 : ret;
-}
-
-struct zcomp_backend zcomp_lzo = {
- .compress = lzo_compress,
- .decompress = lzo_decompress,
- .create = lzo_create,
- .destroy = lzo_destroy,
- .name = "lzo",
-};
diff --git a/drivers/block/zram/zcomp_lzo.h b/drivers/block/zram/zcomp_lzo.h
deleted file mode 100644
index 128c5807f..000000000
--- a/drivers/block/zram/zcomp_lzo.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2014 Sergey Senozhatsky.
- *
- * 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.
- */
-
-#ifndef _ZCOMP_LZO_H_
-#define _ZCOMP_LZO_H_
-
-#include "zcomp.h"
-
-extern struct zcomp_backend zcomp_lzo;
-
-#endif /* _ZCOMP_LZO_H_ */
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
deleted file mode 100644
index 4f943759d..000000000
--- a/drivers/char/genrtc.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * Real Time Clock interface for
- * - q40 and other m68k machines,
- * - HP PARISC machines
- * - PowerPC machines
- * emulate some RTC irq capabilities in software
- *
- * Copyright (C) 1999 Richard Zidlicky
- *
- * based on Paul Gortmaker's rtc.c device and
- * Sam Creasey Generic rtc driver
- *
- * This driver allows use of the real time clock (built into
- * nearly all computers) from user space. It exports the /dev/rtc
- * interface supporting various ioctl() and also the /proc/driver/rtc
- * pseudo-file for status information.
- *
- * The ioctls can be used to set the interrupt behaviour where
- * supported.
- *
- * The /dev/rtc interface will block on reads until an interrupt
- * has been received. If a RTC interrupt has already happened,
- * it will output an unsigned long and then block. The output value
- * contains the interrupt status in the low byte and the number of
- * interrupts since the last read in the remaining high bytes. The
- * /dev/rtc interface can also be used with the select(2) call.
- *
- * 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.
- *
-
- * 1.01 fix for 2.3.X rz@linux-m68k.org
- * 1.02 merged with code from genrtc.c rz@linux-m68k.org
- * 1.03 make it more portable zippel@linux-m68k.org
- * 1.04 removed useless timer code rz@linux-m68k.org
- * 1.05 portable RTC_UIE emulation rz@linux-m68k.org
- * 1.06 set_rtc_time can return an error trini@kernel.crashing.org
- * 1.07 ported to HP PARISC (hppa) Helge Deller <deller@gmx.de>
- */
-
-#define RTC_VERSION "1.07"
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/fcntl.h>
-
-#include <linux/rtc.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/rtc.h>
-
-/*
- * We sponge a minor off of the misc major. No need slurping
- * up another valuable major dev number for this. If you add
- * an ioctl, make sure you don't conflict with SPARC's RTC
- * ioctls.
- */
-
-static DEFINE_MUTEX(gen_rtc_mutex);
-static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
-
-/*
- * Bits in gen_rtc_status.
- */
-
-#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
-
-static unsigned char gen_rtc_status; /* bitmapped status byte. */
-static unsigned long gen_rtc_irq_data; /* our output to the world */
-
-/* months start at 0 now */
-static unsigned char days_in_mo[] =
-{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-static int irq_active;
-
-#ifdef CONFIG_GEN_RTC_X
-static struct work_struct genrtc_task;
-static struct timer_list timer_task;
-
-static unsigned int oldsecs;
-static int lostint;
-static unsigned long tt_exp;
-
-static void gen_rtc_timer(unsigned long data);
-
-static volatile int stask_active; /* schedule_work */
-static volatile int ttask_active; /* timer_task */
-static int stop_rtc_timers; /* don't requeue tasks */
-static DEFINE_SPINLOCK(gen_rtc_lock);
-
-static void gen_rtc_interrupt(unsigned long arg);
-
-/*
- * Routine to poll RTC seconds field for change as often as possible,
- * after first RTC_UIE use timer to reduce polling
- */
-static void genrtc_troutine(struct work_struct *work)
-{
- unsigned int tmp = get_rtc_ss();
-
- if (stop_rtc_timers) {
- stask_active = 0;
- return;
- }
-
- if (oldsecs != tmp){
- oldsecs = tmp;
-
- timer_task.function = gen_rtc_timer;
- timer_task.expires = jiffies + HZ - (HZ/10);
- tt_exp=timer_task.expires;
- ttask_active=1;
- stask_active=0;
- add_timer(&timer_task);
-
- gen_rtc_interrupt(0);
- } else if (schedule_work(&genrtc_task) == 0)
- stask_active = 0;
-}
-
-static void gen_rtc_timer(unsigned long data)
-{
- lostint = get_rtc_ss() - oldsecs ;
- if (lostint<0)
- lostint = 60 - lostint;
- if (time_after(jiffies, tt_exp))
- printk(KERN_INFO "genrtc: timer task delayed by %ld jiffies\n",
- jiffies-tt_exp);
- ttask_active=0;
- stask_active=1;
- if ((schedule_work(&genrtc_task) == 0))
- stask_active = 0;
-}
-
-/*
- * call gen_rtc_interrupt function to signal an RTC_UIE,
- * arg is unused.
- * Could be invoked either from a real interrupt handler or
- * from some routine that periodically (eg 100HZ) monitors
- * whether RTC_SECS changed
- */
-static void gen_rtc_interrupt(unsigned long arg)
-{
- /* We store the status in the low byte and the number of
- * interrupts received since the last read in the remainder
- * of rtc_irq_data. */
-
- gen_rtc_irq_data += 0x100;
- gen_rtc_irq_data &= ~0xff;
- gen_rtc_irq_data |= RTC_UIE;
-
- if (lostint){
- printk("genrtc: system delaying clock ticks?\n");
- /* increment count so that userspace knows something is wrong */
- gen_rtc_irq_data += ((lostint-1)<<8);
- lostint = 0;
- }
-
- wake_up_interruptible(&gen_rtc_wait);
-}
-
-/*
- * Now all the various file operations that we export.
- */
-static ssize_t gen_rtc_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned long data;
- ssize_t retval;
-
- if (count != sizeof (unsigned int) && count != sizeof (unsigned long))
- return -EINVAL;
-
- if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data)
- return -EAGAIN;
-
- retval = wait_event_interruptible(gen_rtc_wait,
- (data = xchg(&gen_rtc_irq_data, 0)));
- if (retval)
- goto out;
-
- /* first test allows optimizer to nuke this case for 32-bit machines */
- if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
- unsigned int uidata = data;
- retval = put_user(uidata, (unsigned int __user *)buf) ?:
- sizeof(unsigned int);
- }
- else {
- retval = put_user(data, (unsigned long __user *)buf) ?:
- sizeof(unsigned long);
- }
-out:
- return retval;
-}
-
-static unsigned int gen_rtc_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- poll_wait(file, &gen_rtc_wait, wait);
- if (gen_rtc_irq_data != 0)
- return POLLIN | POLLRDNORM;
- return 0;
-}
-
-#endif
-
-/*
- * Used to disable/enable interrupts, only RTC_UIE supported
- * We also clear out any old irq data after an ioctl() that
- * meddles with the interrupt enable/disable bits.
- */
-
-static inline void gen_clear_rtc_irq_bit(unsigned char bit)
-{
-#ifdef CONFIG_GEN_RTC_X
- stop_rtc_timers = 1;
- if (ttask_active){
- del_timer_sync(&timer_task);
- ttask_active = 0;
- }
- while (stask_active)
- schedule();
-
- spin_lock(&gen_rtc_lock);
- irq_active = 0;
- spin_unlock(&gen_rtc_lock);
-#endif
-}
-
-static inline int gen_set_rtc_irq_bit(unsigned char bit)
-{
-#ifdef CONFIG_GEN_RTC_X
- spin_lock(&gen_rtc_lock);
- if ( !irq_active ) {
- irq_active = 1;
- stop_rtc_timers = 0;
- lostint = 0;
- INIT_WORK(&genrtc_task, genrtc_troutine);
- oldsecs = get_rtc_ss();
- init_timer(&timer_task);
-
- stask_active = 1;
- if (schedule_work(&genrtc_task) == 0){
- stask_active = 0;
- }
- }
- spin_unlock(&gen_rtc_lock);
- gen_rtc_irq_data = 0;
- return 0;
-#else
- return -EINVAL;
-#endif
-}
-
-static int gen_rtc_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct rtc_time wtime;
- struct rtc_pll_info pll;
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
-
- case RTC_PLL_GET:
- if (get_rtc_pll(&pll))
- return -EINVAL;
- else
- return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0;
-
- case RTC_PLL_SET:
- if (!capable(CAP_SYS_TIME))
- return -EACCES;
- if (copy_from_user(&pll, argp, sizeof(pll)))
- return -EFAULT;
- return set_rtc_pll(&pll);
-
- case RTC_UIE_OFF: /* disable ints from RTC updates. */
- gen_clear_rtc_irq_bit(RTC_UIE);
- return 0;
-
- case RTC_UIE_ON: /* enable ints for RTC updates. */
- return gen_set_rtc_irq_bit(RTC_UIE);
-
- case RTC_RD_TIME: /* Read the time/date from RTC */
- /* this doesn't get week-day, who cares */
- memset(&wtime, 0, sizeof(wtime));
- get_rtc_time(&wtime);
-
- return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0;
-
- case RTC_SET_TIME: /* Set the RTC */
- {
- int year;
- unsigned char leap_yr;
-
- if (!capable(CAP_SYS_TIME))
- return -EACCES;
-
- if (copy_from_user(&wtime, argp, sizeof(wtime)))
- return -EFAULT;
-
- year = wtime.tm_year + 1900;
- leap_yr = ((!(year % 4) && (year % 100)) ||
- !(year % 400));
-
- if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1))
- return -EINVAL;
-
- if (wtime.tm_mday < 0 || wtime.tm_mday >
- (days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr)))
- return -EINVAL;
-
- if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 ||
- wtime.tm_min < 0 || wtime.tm_min >= 60 ||
- wtime.tm_sec < 0 || wtime.tm_sec >= 60)
- return -EINVAL;
-
- return set_rtc_time(&wtime);
- }
- }
-
- return -EINVAL;
-}
-
-static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int ret;
-
- mutex_lock(&gen_rtc_mutex);
- ret = gen_rtc_ioctl(file, cmd, arg);
- mutex_unlock(&gen_rtc_mutex);
-
- return ret;
-}
-
-/*
- * We enforce only one user at a time here with the open/close.
- * Also clear the previous interrupt data on an open, and clean
- * up things on a close.
- */
-
-static int gen_rtc_open(struct inode *inode, struct file *file)
-{
- mutex_lock(&gen_rtc_mutex);
- if (gen_rtc_status & RTC_IS_OPEN) {
- mutex_unlock(&gen_rtc_mutex);
- return -EBUSY;
- }
-
- gen_rtc_status |= RTC_IS_OPEN;
- gen_rtc_irq_data = 0;
- irq_active = 0;
- mutex_unlock(&gen_rtc_mutex);
-
- return 0;
-}
-
-static int gen_rtc_release(struct inode *inode, struct file *file)
-{
- /*
- * Turn off all interrupts once the device is no longer
- * in use and clear the data.
- */
-
- gen_clear_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE);
-
- gen_rtc_status &= ~RTC_IS_OPEN;
- return 0;
-}
-
-
-#ifdef CONFIG_PROC_FS
-
-/*
- * Info exported via "/proc/driver/rtc".
- */
-
-static int gen_rtc_proc_show(struct seq_file *m, void *v)
-{
- struct rtc_time tm;
- unsigned int flags;
- struct rtc_pll_info pll;
-
- flags = get_rtc_time(&tm);
-
- seq_printf(m,
- "rtc_time\t: %02d:%02d:%02d\n"
- "rtc_date\t: %04d-%02d-%02d\n"
- "rtc_epoch\t: %04u\n",
- tm.tm_hour, tm.tm_min, tm.tm_sec,
- tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1900);
-
- tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
-
- seq_puts(m, "alarm\t\t: ");
- if (tm.tm_hour <= 24)
- seq_printf(m, "%02d:", tm.tm_hour);
- else
- seq_puts(m, "**:");
-
- if (tm.tm_min <= 59)
- seq_printf(m, "%02d:", tm.tm_min);
- else
- seq_puts(m, "**:");
-
- if (tm.tm_sec <= 59)
- seq_printf(m, "%02d\n", tm.tm_sec);
- else
- seq_puts(m, "**\n");
-
- seq_printf(m,
- "DST_enable\t: %s\n"
- "BCD\t\t: %s\n"
- "24hr\t\t: %s\n"
- "square_wave\t: %s\n"
- "alarm_IRQ\t: %s\n"
- "update_IRQ\t: %s\n"
- "periodic_IRQ\t: %s\n"
- "periodic_freq\t: %ld\n"
- "batt_status\t: %s\n",
- (flags & RTC_DST_EN) ? "yes" : "no",
- (flags & RTC_DM_BINARY) ? "no" : "yes",
- (flags & RTC_24H) ? "yes" : "no",
- (flags & RTC_SQWE) ? "yes" : "no",
- (flags & RTC_AIE) ? "yes" : "no",
- irq_active ? "yes" : "no",
- (flags & RTC_PIE) ? "yes" : "no",
- 0L /* freq */,
- (flags & RTC_BATT_BAD) ? "bad" : "okay");
- if (!get_rtc_pll(&pll))
- seq_printf(m,
- "PLL adjustment\t: %d\n"
- "PLL max +ve adjustment\t: %d\n"
- "PLL max -ve adjustment\t: %d\n"
- "PLL +ve adjustment factor\t: %d\n"
- "PLL -ve adjustment factor\t: %d\n"
- "PLL frequency\t: %ld\n",
- pll.pll_value,
- pll.pll_max,
- pll.pll_min,
- pll.pll_posmult,
- pll.pll_negmult,
- pll.pll_clock);
- return 0;
-}
-
-static int gen_rtc_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gen_rtc_proc_show, NULL);
-}
-
-static const struct file_operations gen_rtc_proc_fops = {
- .open = gen_rtc_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int __init gen_rtc_proc_init(void)
-{
- struct proc_dir_entry *r;
-
- r = proc_create("driver/rtc", 0, NULL, &gen_rtc_proc_fops);
- if (!r)
- return -ENOMEM;
- return 0;
-}
-#else
-static inline int gen_rtc_proc_init(void) { return 0; }
-#endif /* CONFIG_PROC_FS */
-
-
-/*
- * The various file operations we support.
- */
-
-static const struct file_operations gen_rtc_fops = {
- .owner = THIS_MODULE,
-#ifdef CONFIG_GEN_RTC_X
- .read = gen_rtc_read,
- .poll = gen_rtc_poll,
-#endif
- .unlocked_ioctl = gen_rtc_unlocked_ioctl,
- .open = gen_rtc_open,
- .release = gen_rtc_release,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice rtc_gen_dev =
-{
- .minor = RTC_MINOR,
- .name = "rtc",
- .fops = &gen_rtc_fops,
-};
-
-static int __init rtc_generic_init(void)
-{
- int retval;
-
- printk(KERN_INFO "Generic RTC Driver v%s\n", RTC_VERSION);
-
- retval = misc_register(&rtc_gen_dev);
- if (retval < 0)
- return retval;
-
- retval = gen_rtc_proc_init();
- if (retval) {
- misc_deregister(&rtc_gen_dev);
- return retval;
- }
-
- return 0;
-}
-
-static void __exit rtc_generic_exit(void)
-{
- remove_proc_entry ("driver/rtc", NULL);
- misc_deregister(&rtc_gen_dev);
-}
-
-
-module_init(rtc_generic_init);
-module_exit(rtc_generic_exit);
-
-MODULE_AUTHOR("Richard Zidlicky");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(RTC_MINOR);
diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c
deleted file mode 100644
index d920d410b..000000000
--- a/drivers/clk/meson/clkc.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2015 Endless Mobile, Inc.
- * Author: Carlo Caione <carlo@endlessm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/clk-provider.h>
-#include <linux/mfd/syscon.h>
-#include <linux/slab.h>
-
-#include "clkc.h"
-
-static DEFINE_SPINLOCK(clk_lock);
-
-static struct clk **clks;
-static struct clk_onecell_data clk_data;
-
-struct clk ** __init meson_clk_init(struct device_node *np,
- unsigned long nr_clks)
-{
- clks = kcalloc(nr_clks, sizeof(*clks), GFP_KERNEL);
- if (!clks)
- return ERR_PTR(-ENOMEM);
-
- clk_data.clks = clks;
- clk_data.clk_num = nr_clks;
- of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-
- return clks;
-}
-
-static void meson_clk_add_lookup(struct clk *clk, unsigned int id)
-{
- if (clks && id)
- clks[id] = clk;
-}
-
-static struct clk * __init
-meson_clk_register_composite(const struct clk_conf *clk_conf,
- void __iomem *clk_base)
-{
- struct clk *clk;
- struct clk_mux *mux = NULL;
- struct clk_divider *div = NULL;
- struct clk_gate *gate = NULL;
- const struct clk_ops *mux_ops = NULL;
- const struct composite_conf *composite_conf;
-
- composite_conf = clk_conf->conf.composite;
-
- if (clk_conf->num_parents > 1) {
- mux = kzalloc(sizeof(*mux), GFP_KERNEL);
- if (!mux)
- return ERR_PTR(-ENOMEM);
-
- mux->reg = clk_base + clk_conf->reg_off
- + composite_conf->mux_parm.reg_off;
- mux->shift = composite_conf->mux_parm.shift;
- mux->mask = BIT(composite_conf->mux_parm.width) - 1;
- mux->flags = composite_conf->mux_flags;
- mux->lock = &clk_lock;
- mux->table = composite_conf->mux_table;
- mux_ops = (composite_conf->mux_flags & CLK_MUX_READ_ONLY) ?
- &clk_mux_ro_ops : &clk_mux_ops;
- }
-
- if (MESON_PARM_APPLICABLE(&composite_conf->div_parm)) {
- div = kzalloc(sizeof(*div), GFP_KERNEL);
- if (!div) {
- clk = ERR_PTR(-ENOMEM);
- goto error;
- }
-
- div->reg = clk_base + clk_conf->reg_off
- + composite_conf->div_parm.reg_off;
- div->shift = composite_conf->div_parm.shift;
- div->width = composite_conf->div_parm.width;
- div->lock = &clk_lock;
- div->flags = composite_conf->div_flags;
- div->table = composite_conf->div_table;
- }
-
- if (MESON_PARM_APPLICABLE(&composite_conf->gate_parm)) {
- gate = kzalloc(sizeof(*gate), GFP_KERNEL);
- if (!gate) {
- clk = ERR_PTR(-ENOMEM);
- goto error;
- }
-
- gate->reg = clk_base + clk_conf->reg_off
- + composite_conf->div_parm.reg_off;
- gate->bit_idx = composite_conf->gate_parm.shift;
- gate->flags = composite_conf->gate_flags;
- gate->lock = &clk_lock;
- }
-
- clk = clk_register_composite(NULL, clk_conf->clk_name,
- clk_conf->clks_parent,
- clk_conf->num_parents,
- mux ? &mux->hw : NULL, mux_ops,
- div ? &div->hw : NULL, &clk_divider_ops,
- gate ? &gate->hw : NULL, &clk_gate_ops,
- clk_conf->flags);
- if (IS_ERR(clk))
- goto error;
-
- return clk;
-
-error:
- kfree(gate);
- kfree(div);
- kfree(mux);
-
- return clk;
-}
-
-static struct clk * __init
-meson_clk_register_fixed_factor(const struct clk_conf *clk_conf,
- void __iomem *clk_base)
-{
- struct clk *clk;
- const struct fixed_fact_conf *fixed_fact_conf;
- const struct parm *p;
- unsigned int mult, div;
- u32 reg;
-
- fixed_fact_conf = &clk_conf->conf.fixed_fact;
-
- mult = clk_conf->conf.fixed_fact.mult;
- div = clk_conf->conf.fixed_fact.div;
-
- if (!mult) {
- mult = 1;
- p = &fixed_fact_conf->mult_parm;
- if (MESON_PARM_APPLICABLE(p)) {
- reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
- mult = PARM_GET(p->width, p->shift, reg);
- }
- }
-
- if (!div) {
- div = 1;
- p = &fixed_fact_conf->div_parm;
- if (MESON_PARM_APPLICABLE(p)) {
- reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
- mult = PARM_GET(p->width, p->shift, reg);
- }
- }
-
- clk = clk_register_fixed_factor(NULL,
- clk_conf->clk_name,
- clk_conf->clks_parent[0],
- clk_conf->flags,
- mult, div);
-
- return clk;
-}
-
-static struct clk * __init
-meson_clk_register_fixed_rate(const struct clk_conf *clk_conf,
- void __iomem *clk_base)
-{
- struct clk *clk;
- const struct fixed_rate_conf *fixed_rate_conf;
- const struct parm *r;
- unsigned long rate;
- u32 reg;
-
- fixed_rate_conf = &clk_conf->conf.fixed_rate;
- rate = fixed_rate_conf->rate;
-
- if (!rate) {
- r = &fixed_rate_conf->rate_parm;
- reg = readl(clk_base + clk_conf->reg_off + r->reg_off);
- rate = PARM_GET(r->width, r->shift, reg);
- }
-
- rate *= 1000000;
-
- clk = clk_register_fixed_rate(NULL,
- clk_conf->clk_name,
- clk_conf->num_parents
- ? clk_conf->clks_parent[0] : NULL,
- clk_conf->flags, rate);
-
- return clk;
-}
-
-void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
- unsigned int nr_confs,
- void __iomem *clk_base)
-{
- unsigned int i;
- struct clk *clk = NULL;
-
- for (i = 0; i < nr_confs; i++) {
- const struct clk_conf *clk_conf = &clk_confs[i];
-
- switch (clk_conf->clk_type) {
- case CLK_FIXED_RATE:
- clk = meson_clk_register_fixed_rate(clk_conf,
- clk_base);
- break;
- case CLK_FIXED_FACTOR:
- clk = meson_clk_register_fixed_factor(clk_conf,
- clk_base);
- break;
- case CLK_COMPOSITE:
- clk = meson_clk_register_composite(clk_conf,
- clk_base);
- break;
- case CLK_CPU:
- clk = meson_clk_register_cpu(clk_conf, clk_base,
- &clk_lock);
- break;
- case CLK_PLL:
- clk = meson_clk_register_pll(clk_conf, clk_base,
- &clk_lock);
- break;
- default:
- clk = NULL;
- }
-
- if (!clk) {
- pr_err("%s: unknown clock type %d\n", __func__,
- clk_conf->clk_type);
- continue;
- }
-
- if (IS_ERR(clk)) {
- pr_warn("%s: Unable to create %s clock\n", __func__,
- clk_conf->clk_name);
- continue;
- }
-
- meson_clk_add_lookup(clk, clk_conf->clk_id);
- }
-}
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index a70367f53..af8825ad2 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -30,7 +30,7 @@ struct cs_dbs_tuners {
};
/* Conservative governor macros */
-#ifdef CONFIG_SCHED_BFS
+#ifdef CONFIG_SCHED_MUQSS
#define DEF_FREQUENCY_UP_THRESHOLD (63)
#define DEF_FREQUENCY_DOWN_THRESHOLD (26)
#else
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 58d6fe616..6fd9fc111 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -20,7 +20,7 @@
#include "cpufreq_ondemand.h"
/* On-demand governor macros */
-#ifdef CONFIG_SCHED_BFS
+#ifdef CONFIG_SCHED_MUQSS
#define DEF_FREQUENCY_UP_THRESHOLD (63)
#else
#define DEF_FREQUENCY_UP_THRESHOLD (80)
diff --git a/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1 b/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
deleted file mode 100644
index f0066adb7..000000000
--- a/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
+++ /dev/null
@@ -1,11 +0,0 @@
-RsaPrivKey ::= SEQUENCE {
- version INTEGER,
- n INTEGER ({ qat_rsa_get_n }),
- e INTEGER ({ qat_rsa_get_e }),
- d INTEGER ({ qat_rsa_get_d }),
- prime1 INTEGER,
- prime2 INTEGER,
- exponent1 INTEGER,
- exponent2 INTEGER,
- coefficient INTEGER
-}
diff --git a/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1 b/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1
deleted file mode 100644
index bd667b31a..000000000
--- a/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1
+++ /dev/null
@@ -1,4 +0,0 @@
-RsaPubKey ::= SEQUENCE {
- n INTEGER ({ qat_rsa_get_n }),
- e INTEGER ({ qat_rsa_get_e })
-}
diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
deleted file mode 100644
index df9118540..000000000
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ /dev/null
@@ -1,2310 +0,0 @@
-/*
- * DMA driver for Xilinx Video DMA Engine
- *
- * Copyright (C) 2010-2014 Xilinx, Inc. All rights reserved.
- *
- * Based on the Freescale DMA driver.
- *
- * Description:
- * The AXI Video Direct Memory Access (AXI VDMA) core is a soft Xilinx IP
- * core that provides high-bandwidth direct memory access between memory
- * and AXI4-Stream type video target peripherals. The core provides efficient
- * two dimensional DMA operations with independent asynchronous read (S2MM)
- * and write (MM2S) channel operation. It can be configured to have either
- * one channel or two channels. If configured as two channels, one is to
- * transmit to the video device (MM2S) and another is to receive from the
- * video device (S2MM). Initialization, status, interrupt and management
- * registers are accessed through an AXI4-Lite slave interface.
- *
- * The AXI Direct Memory Access (AXI DMA) core is a soft Xilinx IP core that
- * provides high-bandwidth one dimensional direct memory access between memory
- * and AXI4-Stream target peripherals. It supports one receive and one
- * transmit channel, both of them optional at synthesis time.
- *
- * The AXI CDMA, is a soft IP, which provides high-bandwidth Direct Memory
- * Access (DMA) between a memory-mapped source address and a memory-mapped
- * destination address.
- *
- * 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.
- */
-
-#include <linux/bitops.h>
-#include <linux/dmapool.h>
-#include <linux/dma/xilinx_dma.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_dma.h>
-#include <linux/of_platform.h>
-#include <linux/of_irq.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-
-#include "../dmaengine.h"
-
-/* Register/Descriptor Offsets */
-#define XILINX_DMA_MM2S_CTRL_OFFSET 0x0000
-#define XILINX_DMA_S2MM_CTRL_OFFSET 0x0030
-#define XILINX_VDMA_MM2S_DESC_OFFSET 0x0050
-#define XILINX_VDMA_S2MM_DESC_OFFSET 0x00a0
-
-/* Control Registers */
-#define XILINX_DMA_REG_DMACR 0x0000
-#define XILINX_DMA_DMACR_DELAY_MAX 0xff
-#define XILINX_DMA_DMACR_DELAY_SHIFT 24
-#define XILINX_DMA_DMACR_FRAME_COUNT_MAX 0xff
-#define XILINX_DMA_DMACR_FRAME_COUNT_SHIFT 16
-#define XILINX_DMA_DMACR_ERR_IRQ BIT(14)
-#define XILINX_DMA_DMACR_DLY_CNT_IRQ BIT(13)
-#define XILINX_DMA_DMACR_FRM_CNT_IRQ BIT(12)
-#define XILINX_DMA_DMACR_MASTER_SHIFT 8
-#define XILINX_DMA_DMACR_FSYNCSRC_SHIFT 5
-#define XILINX_DMA_DMACR_FRAMECNT_EN BIT(4)
-#define XILINX_DMA_DMACR_GENLOCK_EN BIT(3)
-#define XILINX_DMA_DMACR_RESET BIT(2)
-#define XILINX_DMA_DMACR_CIRC_EN BIT(1)
-#define XILINX_DMA_DMACR_RUNSTOP BIT(0)
-#define XILINX_DMA_DMACR_FSYNCSRC_MASK GENMASK(6, 5)
-
-#define XILINX_DMA_REG_DMASR 0x0004
-#define XILINX_DMA_DMASR_EOL_LATE_ERR BIT(15)
-#define XILINX_DMA_DMASR_ERR_IRQ BIT(14)
-#define XILINX_DMA_DMASR_DLY_CNT_IRQ BIT(13)
-#define XILINX_DMA_DMASR_FRM_CNT_IRQ BIT(12)
-#define XILINX_DMA_DMASR_SOF_LATE_ERR BIT(11)
-#define XILINX_DMA_DMASR_SG_DEC_ERR BIT(10)
-#define XILINX_DMA_DMASR_SG_SLV_ERR BIT(9)
-#define XILINX_DMA_DMASR_EOF_EARLY_ERR BIT(8)
-#define XILINX_DMA_DMASR_SOF_EARLY_ERR BIT(7)
-#define XILINX_DMA_DMASR_DMA_DEC_ERR BIT(6)
-#define XILINX_DMA_DMASR_DMA_SLAVE_ERR BIT(5)
-#define XILINX_DMA_DMASR_DMA_INT_ERR BIT(4)
-#define XILINX_DMA_DMASR_IDLE BIT(1)
-#define XILINX_DMA_DMASR_HALTED BIT(0)
-#define XILINX_DMA_DMASR_DELAY_MASK GENMASK(31, 24)
-#define XILINX_DMA_DMASR_FRAME_COUNT_MASK GENMASK(23, 16)
-
-#define XILINX_DMA_REG_CURDESC 0x0008
-#define XILINX_DMA_REG_TAILDESC 0x0010
-#define XILINX_DMA_REG_REG_INDEX 0x0014
-#define XILINX_DMA_REG_FRMSTORE 0x0018
-#define XILINX_DMA_REG_THRESHOLD 0x001c
-#define XILINX_DMA_REG_FRMPTR_STS 0x0024
-#define XILINX_DMA_REG_PARK_PTR 0x0028
-#define XILINX_DMA_PARK_PTR_WR_REF_SHIFT 8
-#define XILINX_DMA_PARK_PTR_RD_REF_SHIFT 0
-#define XILINX_DMA_REG_VDMA_VERSION 0x002c
-
-/* Register Direct Mode Registers */
-#define XILINX_DMA_REG_VSIZE 0x0000
-#define XILINX_DMA_REG_HSIZE 0x0004
-
-#define XILINX_DMA_REG_FRMDLY_STRIDE 0x0008
-#define XILINX_DMA_FRMDLY_STRIDE_FRMDLY_SHIFT 24
-#define XILINX_DMA_FRMDLY_STRIDE_STRIDE_SHIFT 0
-
-#define XILINX_VDMA_REG_START_ADDRESS(n) (0x000c + 4 * (n))
-#define XILINX_VDMA_REG_START_ADDRESS_64(n) (0x000c + 8 * (n))
-
-/* HW specific definitions */
-#define XILINX_DMA_MAX_CHANS_PER_DEVICE 0x2
-
-#define XILINX_DMA_DMAXR_ALL_IRQ_MASK \
- (XILINX_DMA_DMASR_FRM_CNT_IRQ | \
- XILINX_DMA_DMASR_DLY_CNT_IRQ | \
- XILINX_DMA_DMASR_ERR_IRQ)
-
-#define XILINX_DMA_DMASR_ALL_ERR_MASK \
- (XILINX_DMA_DMASR_EOL_LATE_ERR | \
- XILINX_DMA_DMASR_SOF_LATE_ERR | \
- XILINX_DMA_DMASR_SG_DEC_ERR | \
- XILINX_DMA_DMASR_SG_SLV_ERR | \
- XILINX_DMA_DMASR_EOF_EARLY_ERR | \
- XILINX_DMA_DMASR_SOF_EARLY_ERR | \
- XILINX_DMA_DMASR_DMA_DEC_ERR | \
- XILINX_DMA_DMASR_DMA_SLAVE_ERR | \
- XILINX_DMA_DMASR_DMA_INT_ERR)
-
-/*
- * Recoverable errors are DMA Internal error, SOF Early, EOF Early
- * and SOF Late. They are only recoverable when C_FLUSH_ON_FSYNC
- * is enabled in the h/w system.
- */
-#define XILINX_DMA_DMASR_ERR_RECOVER_MASK \
- (XILINX_DMA_DMASR_SOF_LATE_ERR | \
- XILINX_DMA_DMASR_EOF_EARLY_ERR | \
- XILINX_DMA_DMASR_SOF_EARLY_ERR | \
- XILINX_DMA_DMASR_DMA_INT_ERR)
-
-/* Axi VDMA Flush on Fsync bits */
-#define XILINX_DMA_FLUSH_S2MM 3
-#define XILINX_DMA_FLUSH_MM2S 2
-#define XILINX_DMA_FLUSH_BOTH 1
-
-/* Delay loop counter to prevent hardware failure */
-#define XILINX_DMA_LOOP_COUNT 1000000
-
-/* AXI DMA Specific Registers/Offsets */
-#define XILINX_DMA_REG_SRCDSTADDR 0x18
-#define XILINX_DMA_REG_BTT 0x28
-
-/* AXI DMA Specific Masks/Bit fields */
-#define XILINX_DMA_MAX_TRANS_LEN GENMASK(22, 0)
-#define XILINX_DMA_CR_COALESCE_MAX GENMASK(23, 16)
-#define XILINX_DMA_CR_COALESCE_SHIFT 16
-#define XILINX_DMA_BD_SOP BIT(27)
-#define XILINX_DMA_BD_EOP BIT(26)
-#define XILINX_DMA_COALESCE_MAX 255
-#define XILINX_DMA_NUM_APP_WORDS 5
-
-/* AXI CDMA Specific Registers/Offsets */
-#define XILINX_CDMA_REG_SRCADDR 0x18
-#define XILINX_CDMA_REG_DSTADDR 0x20
-
-/* AXI CDMA Specific Masks */
-#define XILINX_CDMA_CR_SGMODE BIT(3)
-
-/**
- * struct xilinx_vdma_desc_hw - Hardware Descriptor
- * @next_desc: Next Descriptor Pointer @0x00
- * @pad1: Reserved @0x04
- * @buf_addr: Buffer address @0x08
- * @buf_addr_msb: MSB of Buffer address @0x0C
- * @vsize: Vertical Size @0x10
- * @hsize: Horizontal Size @0x14
- * @stride: Number of bytes between the first
- * pixels of each horizontal line @0x18
- */
-struct xilinx_vdma_desc_hw {
- u32 next_desc;
- u32 pad1;
- u32 buf_addr;
- u32 buf_addr_msb;
- u32 vsize;
- u32 hsize;
- u32 stride;
-} __aligned(64);
-
-/**
- * struct xilinx_axidma_desc_hw - Hardware Descriptor for AXI DMA
- * @next_desc: Next Descriptor Pointer @0x00
- * @pad1: Reserved @0x04
- * @buf_addr: Buffer address @0x08
- * @pad2: Reserved @0x0C
- * @pad3: Reserved @0x10
- * @pad4: Reserved @0x14
- * @control: Control field @0x18
- * @status: Status field @0x1C
- * @app: APP Fields @0x20 - 0x30
- */
-struct xilinx_axidma_desc_hw {
- u32 next_desc;
- u32 pad1;
- u32 buf_addr;
- u32 pad2;
- u32 pad3;
- u32 pad4;
- u32 control;
- u32 status;
- u32 app[XILINX_DMA_NUM_APP_WORDS];
-} __aligned(64);
-
-/**
- * struct xilinx_cdma_desc_hw - Hardware Descriptor
- * @next_desc: Next Descriptor Pointer @0x00
- * @pad1: Reserved @0x04
- * @src_addr: Source address @0x08
- * @pad2: Reserved @0x0C
- * @dest_addr: Destination address @0x10
- * @pad3: Reserved @0x14
- * @control: Control field @0x18
- * @status: Status field @0x1C
- */
-struct xilinx_cdma_desc_hw {
- u32 next_desc;
- u32 pad1;
- u32 src_addr;
- u32 pad2;
- u32 dest_addr;
- u32 pad3;
- u32 control;
- u32 status;
-} __aligned(64);
-
-/**
- * struct xilinx_vdma_tx_segment - Descriptor segment
- * @hw: Hardware descriptor
- * @node: Node in the descriptor segments list
- * @phys: Physical address of segment
- */
-struct xilinx_vdma_tx_segment {
- struct xilinx_vdma_desc_hw hw;
- struct list_head node;
- dma_addr_t phys;
-} __aligned(64);
-
-/**
- * struct xilinx_axidma_tx_segment - Descriptor segment
- * @hw: Hardware descriptor
- * @node: Node in the descriptor segments list
- * @phys: Physical address of segment
- */
-struct xilinx_axidma_tx_segment {
- struct xilinx_axidma_desc_hw hw;
- struct list_head node;
- dma_addr_t phys;
-} __aligned(64);
-
-/**
- * struct xilinx_cdma_tx_segment - Descriptor segment
- * @hw: Hardware descriptor
- * @node: Node in the descriptor segments list
- * @phys: Physical address of segment
- */
-struct xilinx_cdma_tx_segment {
- struct xilinx_cdma_desc_hw hw;
- struct list_head node;
- dma_addr_t phys;
-} __aligned(64);
-
-/**
- * struct xilinx_dma_tx_descriptor - Per Transaction structure
- * @async_tx: Async transaction descriptor
- * @segments: TX segments list
- * @node: Node in the channel descriptors list
- */
-struct xilinx_dma_tx_descriptor {
- struct dma_async_tx_descriptor async_tx;
- struct list_head segments;
- struct list_head node;
-};
-
-/**
- * struct xilinx_dma_chan - Driver specific DMA channel structure
- * @xdev: Driver specific device structure
- * @ctrl_offset: Control registers offset
- * @desc_offset: TX descriptor registers offset
- * @lock: Descriptor operation lock
- * @pending_list: Descriptors waiting
- * @active_list: Descriptors ready to submit
- * @done_list: Complete descriptors
- * @common: DMA common channel
- * @desc_pool: Descriptors pool
- * @dev: The dma device
- * @irq: Channel IRQ
- * @id: Channel ID
- * @direction: Transfer direction
- * @num_frms: Number of frames
- * @has_sg: Support scatter transfers
- * @genlock: Support genlock mode
- * @err: Channel has errors
- * @tasklet: Cleanup work after irq
- * @config: Device configuration info
- * @flush_on_fsync: Flush on Frame sync
- * @desc_pendingcount: Descriptor pending count
- * @ext_addr: Indicates 64 bit addressing is supported by dma channel
- * @desc_submitcount: Descriptor h/w submitted count
- * @residue: Residue for AXI DMA
- * @seg_v: Statically allocated segments base
- * @start_transfer: Differentiate b/w DMA IP's transfer
- */
-struct xilinx_dma_chan {
- struct xilinx_dma_device *xdev;
- u32 ctrl_offset;
- u32 desc_offset;
- spinlock_t lock;
- struct list_head pending_list;
- struct list_head active_list;
- struct list_head done_list;
- struct dma_chan common;
- struct dma_pool *desc_pool;
- struct device *dev;
- int irq;
- int id;
- enum dma_transfer_direction direction;
- int num_frms;
- bool has_sg;
- bool genlock;
- bool err;
- struct tasklet_struct tasklet;
- struct xilinx_vdma_config config;
- bool flush_on_fsync;
- u32 desc_pendingcount;
- bool ext_addr;
- u32 desc_submitcount;
- u32 residue;
- struct xilinx_axidma_tx_segment *seg_v;
- void (*start_transfer)(struct xilinx_dma_chan *chan);
-};
-
-struct xilinx_dma_config {
- enum xdma_ip_type dmatype;
- int (*clk_init)(struct platform_device *pdev, struct clk **axi_clk,
- struct clk **tx_clk, struct clk **txs_clk,
- struct clk **rx_clk, struct clk **rxs_clk);
-};
-
-/**
- * struct xilinx_dma_device - DMA device structure
- * @regs: I/O mapped base address
- * @dev: Device Structure
- * @common: DMA device structure
- * @chan: Driver specific DMA channel
- * @has_sg: Specifies whether Scatter-Gather is present or not
- * @flush_on_fsync: Flush on frame sync
- * @ext_addr: Indicates 64 bit addressing is supported by dma device
- * @pdev: Platform device structure pointer
- * @dma_config: DMA config structure
- * @axi_clk: DMA Axi4-lite interace clock
- * @tx_clk: DMA mm2s clock
- * @txs_clk: DMA mm2s stream clock
- * @rx_clk: DMA s2mm clock
- * @rxs_clk: DMA s2mm stream clock
- */
-struct xilinx_dma_device {
- void __iomem *regs;
- struct device *dev;
- struct dma_device common;
- struct xilinx_dma_chan *chan[XILINX_DMA_MAX_CHANS_PER_DEVICE];
- bool has_sg;
- u32 flush_on_fsync;
- bool ext_addr;
- struct platform_device *pdev;
- const struct xilinx_dma_config *dma_config;
- struct clk *axi_clk;
- struct clk *tx_clk;
- struct clk *txs_clk;
- struct clk *rx_clk;
- struct clk *rxs_clk;
-};
-
-/* Macros */
-#define to_xilinx_chan(chan) \
- container_of(chan, struct xilinx_dma_chan, common)
-#define to_dma_tx_descriptor(tx) \
- container_of(tx, struct xilinx_dma_tx_descriptor, async_tx)
-#define xilinx_dma_poll_timeout(chan, reg, val, cond, delay_us, timeout_us) \
- readl_poll_timeout(chan->xdev->regs + chan->ctrl_offset + reg, val, \
- cond, delay_us, timeout_us)
-
-/* IO accessors */
-static inline u32 dma_read(struct xilinx_dma_chan *chan, u32 reg)
-{
- return ioread32(chan->xdev->regs + reg);
-}
-
-static inline void dma_write(struct xilinx_dma_chan *chan, u32 reg, u32 value)
-{
- iowrite32(value, chan->xdev->regs + reg);
-}
-
-static inline void vdma_desc_write(struct xilinx_dma_chan *chan, u32 reg,
- u32 value)
-{
- dma_write(chan, chan->desc_offset + reg, value);
-}
-
-static inline u32 dma_ctrl_read(struct xilinx_dma_chan *chan, u32 reg)
-{
- return dma_read(chan, chan->ctrl_offset + reg);
-}
-
-static inline void dma_ctrl_write(struct xilinx_dma_chan *chan, u32 reg,
- u32 value)
-{
- dma_write(chan, chan->ctrl_offset + reg, value);
-}
-
-static inline void dma_ctrl_clr(struct xilinx_dma_chan *chan, u32 reg,
- u32 clr)
-{
- dma_ctrl_write(chan, reg, dma_ctrl_read(chan, reg) & ~clr);
-}
-
-static inline void dma_ctrl_set(struct xilinx_dma_chan *chan, u32 reg,
- u32 set)
-{
- dma_ctrl_write(chan, reg, dma_ctrl_read(chan, reg) | set);
-}
-
-/**
- * vdma_desc_write_64 - 64-bit descriptor write
- * @chan: Driver specific VDMA channel
- * @reg: Register to write
- * @value_lsb: lower address of the descriptor.
- * @value_msb: upper address of the descriptor.
- *
- * Since vdma driver is trying to write to a register offset which is not a
- * multiple of 64 bits(ex : 0x5c), we are writing as two separate 32 bits
- * instead of a single 64 bit register write.
- */
-static inline void vdma_desc_write_64(struct xilinx_dma_chan *chan, u32 reg,
- u32 value_lsb, u32 value_msb)
-{
- /* Write the lsb 32 bits*/
- writel(value_lsb, chan->xdev->regs + chan->desc_offset + reg);
-
- /* Write the msb 32 bits */
- writel(value_msb, chan->xdev->regs + chan->desc_offset + reg + 4);
-}
-
-/* -----------------------------------------------------------------------------
- * Descriptors and segments alloc and free
- */
-
-/**
- * xilinx_vdma_alloc_tx_segment - Allocate transaction segment
- * @chan: Driver specific DMA channel
- *
- * Return: The allocated segment on success and NULL on failure.
- */
-static struct xilinx_vdma_tx_segment *
-xilinx_vdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
-{
- struct xilinx_vdma_tx_segment *segment;
- dma_addr_t phys;
-
- segment = dma_pool_zalloc(chan->desc_pool, GFP_ATOMIC, &phys);
- if (!segment)
- return NULL;
-
- segment->phys = phys;
-
- return segment;
-}
-
-/**
- * xilinx_cdma_alloc_tx_segment - Allocate transaction segment
- * @chan: Driver specific DMA channel
- *
- * Return: The allocated segment on success and NULL on failure.
- */
-static struct xilinx_cdma_tx_segment *
-xilinx_cdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
-{
- struct xilinx_cdma_tx_segment *segment;
- dma_addr_t phys;
-
- segment = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys);
- if (!segment)
- return NULL;
-
- memset(segment, 0, sizeof(*segment));
- segment->phys = phys;
-
- return segment;
-}
-
-/**
- * xilinx_axidma_alloc_tx_segment - Allocate transaction segment
- * @chan: Driver specific DMA channel
- *
- * Return: The allocated segment on success and NULL on failure.
- */
-static struct xilinx_axidma_tx_segment *
-xilinx_axidma_alloc_tx_segment(struct xilinx_dma_chan *chan)
-{
- struct xilinx_axidma_tx_segment *segment;
- dma_addr_t phys;
-
- segment = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys);
- if (!segment)
- return NULL;
-
- memset(segment, 0, sizeof(*segment));
- segment->phys = phys;
-
- return segment;
-}
-
-/**
- * xilinx_dma_free_tx_segment - Free transaction segment
- * @chan: Driver specific DMA channel
- * @segment: DMA transaction segment
- */
-static void xilinx_dma_free_tx_segment(struct xilinx_dma_chan *chan,
- struct xilinx_axidma_tx_segment *segment)
-{
- dma_pool_free(chan->desc_pool, segment, segment->phys);
-}
-
-/**
- * xilinx_cdma_free_tx_segment - Free transaction segment
- * @chan: Driver specific DMA channel
- * @segment: DMA transaction segment
- */
-static void xilinx_cdma_free_tx_segment(struct xilinx_dma_chan *chan,
- struct xilinx_cdma_tx_segment *segment)
-{
- dma_pool_free(chan->desc_pool, segment, segment->phys);
-}
-
-/**
- * xilinx_vdma_free_tx_segment - Free transaction segment
- * @chan: Driver specific DMA channel
- * @segment: DMA transaction segment
- */
-static void xilinx_vdma_free_tx_segment(struct xilinx_dma_chan *chan,
- struct xilinx_vdma_tx_segment *segment)
-{
- dma_pool_free(chan->desc_pool, segment, segment->phys);
-}
-
-/**
- * xilinx_dma_tx_descriptor - Allocate transaction descriptor
- * @chan: Driver specific DMA channel
- *
- * Return: The allocated descriptor on success and NULL on failure.
- */
-static struct xilinx_dma_tx_descriptor *
-xilinx_dma_alloc_tx_descriptor(struct xilinx_dma_chan *chan)
-{
- struct xilinx_dma_tx_descriptor *desc;
-
- desc = kzalloc(sizeof(*desc), GFP_KERNEL);
- if (!desc)
- return NULL;
-
- INIT_LIST_HEAD(&desc->segments);
-
- return desc;
-}
-
-/**
- * xilinx_dma_free_tx_descriptor - Free transaction descriptor
- * @chan: Driver specific DMA channel
- * @desc: DMA transaction descriptor
- */
-static void
-xilinx_dma_free_tx_descriptor(struct xilinx_dma_chan *chan,
- struct xilinx_dma_tx_descriptor *desc)
-{
- struct xilinx_vdma_tx_segment *segment, *next;
- struct xilinx_cdma_tx_segment *cdma_segment, *cdma_next;
- struct xilinx_axidma_tx_segment *axidma_segment, *axidma_next;
-
- if (!desc)
- return;
-
- if (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
- list_for_each_entry_safe(segment, next, &desc->segments, node) {
- list_del(&segment->node);
- xilinx_vdma_free_tx_segment(chan, segment);
- }
- } else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
- list_for_each_entry_safe(cdma_segment, cdma_next,
- &desc->segments, node) {
- list_del(&cdma_segment->node);
- xilinx_cdma_free_tx_segment(chan, cdma_segment);
- }
- } else {
- list_for_each_entry_safe(axidma_segment, axidma_next,
- &desc->segments, node) {
- list_del(&axidma_segment->node);
- xilinx_dma_free_tx_segment(chan, axidma_segment);
- }
- }
-
- kfree(desc);
-}
-
-/* Required functions */
-
-/**
- * xilinx_dma_free_desc_list - Free descriptors list
- * @chan: Driver specific DMA channel
- * @list: List to parse and delete the descriptor
- */
-static void xilinx_dma_free_desc_list(struct xilinx_dma_chan *chan,
- struct list_head *list)
-{
- struct xilinx_dma_tx_descriptor *desc, *next;
-
- list_for_each_entry_safe(desc, next, list, node) {
- list_del(&desc->node);
- xilinx_dma_free_tx_descriptor(chan, desc);
- }
-}
-
-/**
- * xilinx_dma_free_descriptors - Free channel descriptors
- * @chan: Driver specific DMA channel
- */
-static void xilinx_dma_free_descriptors(struct xilinx_dma_chan *chan)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&chan->lock, flags);
-
- xilinx_dma_free_desc_list(chan, &chan->pending_list);
- xilinx_dma_free_desc_list(chan, &chan->done_list);
- xilinx_dma_free_desc_list(chan, &chan->active_list);
-
- spin_unlock_irqrestore(&chan->lock, flags);
-}
-
-/**
- * xilinx_dma_free_chan_resources - Free channel resources
- * @dchan: DMA channel
- */
-static void xilinx_dma_free_chan_resources(struct dma_chan *dchan)
-{
- struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
-
- dev_dbg(chan->dev, "Free all channel resources.\n");
-
- xilinx_dma_free_descriptors(chan);
- if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
- xilinx_dma_free_tx_segment(chan, chan->seg_v);
- dma_pool_destroy(chan->desc_pool);
- chan->desc_pool = NULL;
-}
-
-/**
- * xilinx_dma_chan_desc_cleanup - Clean channel descriptors
- * @chan: Driver specific DMA channel
- */
-static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
-{
- struct xilinx_dma_tx_descriptor *desc, *next;
- unsigned long flags;
-
- spin_lock_irqsave(&chan->lock, flags);
-
- list_for_each_entry_safe(desc, next, &chan->done_list, node) {
- dma_async_tx_callback callback;
- void *callback_param;
-
- /* Remove from the list of running transactions */
- list_del(&desc->node);
-
- /* Run the link descriptor callback function */
- callback = desc->async_tx.callback;
- callback_param = desc->async_tx.callback_param;
- if (callback) {
- spin_unlock_irqrestore(&chan->lock, flags);
- callback(callback_param);
- spin_lock_irqsave(&chan->lock, flags);
- }
-
- /* Run any dependencies, then free the descriptor */
- dma_run_dependencies(&desc->async_tx);
- xilinx_dma_free_tx_descriptor(chan, desc);
- }
-
- spin_unlock_irqrestore(&chan->lock, flags);
-}
-
-/**
- * xilinx_dma_do_tasklet - Schedule completion tasklet
- * @data: Pointer to the Xilinx DMA channel structure
- */
-static void xilinx_dma_do_tasklet(unsigned long data)
-{
- struct xilinx_dma_chan *chan = (struct xilinx_dma_chan *)data;
-
- xilinx_dma_chan_desc_cleanup(chan);
-}
-
-/**
- * xilinx_dma_alloc_chan_resources - Allocate channel resources
- * @dchan: DMA channel
- *
- * Return: '0' on success and failure value on error
- */
-static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
-{
- struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
-
- /* Has this channel already been allocated? */
- if (chan->desc_pool)
- return 0;
-
- /*
- * We need the descriptor to be aligned to 64bytes
- * for meeting Xilinx VDMA specification requirement.
- */
- if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
- chan->desc_pool = dma_pool_create("xilinx_dma_desc_pool",
- chan->dev,
- sizeof(struct xilinx_axidma_tx_segment),
- __alignof__(struct xilinx_axidma_tx_segment),
- 0);
- } else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
- chan->desc_pool = dma_pool_create("xilinx_cdma_desc_pool",
- chan->dev,
- sizeof(struct xilinx_cdma_tx_segment),
- __alignof__(struct xilinx_cdma_tx_segment),
- 0);
- } else {
- chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool",
- chan->dev,
- sizeof(struct xilinx_vdma_tx_segment),
- __alignof__(struct xilinx_vdma_tx_segment),
- 0);
- }
-
- if (!chan->desc_pool) {
- dev_err(chan->dev,
- "unable to allocate channel %d descriptor pool\n",
- chan->id);
- return -ENOMEM;
- }
-
- if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
- /*
- * For AXI DMA case after submitting a pending_list, keep
- * an extra segment allocated so that the "next descriptor"
- * pointer on the tail descriptor always points to a
- * valid descriptor, even when paused after reaching taildesc.
- * This way, it is possible to issue additional
- * transfers without halting and restarting the channel.
- */
- chan->seg_v = xilinx_axidma_alloc_tx_segment(chan);
-
- dma_cookie_init(dchan);
-
- if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
- /* For AXI DMA resetting once channel will reset the
- * other channel as well so enable the interrupts here.
- */
- dma_ctrl_set(chan, XILINX_DMA_REG_DMACR,
- XILINX_DMA_DMAXR_ALL_IRQ_MASK);
- }
-
- if ((chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) && chan->has_sg)
- dma_ctrl_set(chan, XILINX_DMA_REG_DMACR,
- XILINX_CDMA_CR_SGMODE);
-
- return 0;
-}
-
-/**
- * xilinx_dma_tx_status - Get DMA transaction status
- * @dchan: DMA channel
- * @cookie: Transaction identifier
- * @txstate: Transaction state
- *
- * Return: DMA transaction status
- */
-static enum dma_status xilinx_dma_tx_status(struct dma_chan *dchan,
- dma_cookie_t cookie,
- struct dma_tx_state *txstate)
-{
- struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
- struct xilinx_dma_tx_descriptor *desc;
- struct xilinx_axidma_tx_segment *segment;
- struct xilinx_axidma_desc_hw *hw;
- enum dma_status ret;
- unsigned long flags;
- u32 residue = 0;
-
- ret = dma_cookie_status(dchan, cookie, txstate);
- if (ret == DMA_COMPLETE || !txstate)
- return ret;
-
- if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
- spin_lock_irqsave(&chan->lock, flags);
-
- desc = list_last_entry(&chan->active_list,
- struct xilinx_dma_tx_descriptor, node);
- if (chan->has_sg) {
- list_for_each_entry(segment, &desc->segments, node) {
- hw = &segment->hw;
- residue += (hw->control - hw->status) &
- XILINX_DMA_MAX_TRANS_LEN;
- }
- }
- spin_unlock_irqrestore(&chan->lock, flags);
-
- chan->residue = residue;
- dma_set_residue(txstate, chan->residue);
- }
-
- return ret;
-}
-
-/**
- * xilinx_dma_is_running - Check if DMA channel is running
- * @chan: Driver specific DMA channel
- *
- * Return: '1' if running, '0' if not.
- */
-static bool xilinx_dma_is_running(struct xilinx_dma_chan *chan)
-{
- return !(dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
- XILINX_DMA_DMASR_HALTED) &&
- (dma_ctrl_read(chan, XILINX_DMA_REG_DMACR) &
- XILINX_DMA_DMACR_RUNSTOP);
-}
-
-/**
- * xilinx_dma_is_idle - Check if DMA channel is idle
- * @chan: Driver specific DMA channel
- *
- * Return: '1' if idle, '0' if not.
- */
-static bool xilinx_dma_is_idle(struct xilinx_dma_chan *chan)
-{
- return dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
- XILINX_DMA_DMASR_IDLE;
-}
-
-/**
- * xilinx_dma_halt - Halt DMA channel
- * @chan: Driver specific DMA channel
- */
-static void xilinx_dma_halt(struct xilinx_dma_chan *chan)
-{
- int err;
- u32 val;
-
- dma_ctrl_clr(chan, XILINX_DMA_REG_DMACR, XILINX_DMA_DMACR_RUNSTOP);
-
- /* Wait for the hardware to halt */
- err = xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
- (val & XILINX_DMA_DMASR_HALTED), 0,
- XILINX_DMA_LOOP_COUNT);
-
- if (err) {
- dev_err(chan->dev, "Cannot stop channel %p: %x\n",
- chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
- chan->err = true;
- }
-}
-
-/**
- * xilinx_dma_start - Start DMA channel
- * @chan: Driver specific DMA channel
- */
-static void xilinx_dma_start(struct xilinx_dma_chan *chan)
-{
- int err;
- u32 val;
-
- dma_ctrl_set(chan, XILINX_DMA_REG_DMACR, XILINX_DMA_DMACR_RUNSTOP);
-
- /* Wait for the hardware to start */
- err = xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
- !(val & XILINX_DMA_DMASR_HALTED), 0,
- XILINX_DMA_LOOP_COUNT);
-
- if (err) {
- dev_err(chan->dev, "Cannot start channel %p: %x\n",
- chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
-
- chan->err = true;
- }
-}
-
-/**
- * xilinx_vdma_start_transfer - Starts VDMA transfer
- * @chan: Driver specific channel struct pointer
- */
-static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan)
-{
- struct xilinx_vdma_config *config = &chan->config;
- struct xilinx_dma_tx_descriptor *desc, *tail_desc;
- u32 reg;
- struct xilinx_vdma_tx_segment *tail_segment;
-
- /* This function was invoked with lock held */
- if (chan->err)
- return;
-
- if (list_empty(&chan->pending_list))
- return;
-
- desc = list_first_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor, node);
- tail_desc = list_last_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor, node);
-
- tail_segment = list_last_entry(&tail_desc->segments,
- struct xilinx_vdma_tx_segment, node);
-
- /* If it is SG mode and hardware is busy, cannot submit */
- if (chan->has_sg && xilinx_dma_is_running(chan) &&
- !xilinx_dma_is_idle(chan)) {
- dev_dbg(chan->dev, "DMA controller still busy\n");
- return;
- }
-
- /*
- * If hardware is idle, then all descriptors on the running lists are
- * done, start new transfers
- */
- if (chan->has_sg)
- dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
- desc->async_tx.phys);
-
- /* Configure the hardware using info in the config structure */
- reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
-
- if (config->frm_cnt_en)
- reg |= XILINX_DMA_DMACR_FRAMECNT_EN;
- else
- reg &= ~XILINX_DMA_DMACR_FRAMECNT_EN;
-
- /* Configure channel to allow number frame buffers */
- dma_ctrl_write(chan, XILINX_DMA_REG_FRMSTORE,
- chan->desc_pendingcount);
-
- /*
- * With SG, start with circular mode, so that BDs can be fetched.
- * In direct register mode, if not parking, enable circular mode
- */
- if (chan->has_sg || !config->park)
- reg |= XILINX_DMA_DMACR_CIRC_EN;
-
- if (config->park)
- reg &= ~XILINX_DMA_DMACR_CIRC_EN;
-
- dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
-
- if (config->park && (config->park_frm >= 0) &&
- (config->park_frm < chan->num_frms)) {
- if (chan->direction == DMA_MEM_TO_DEV)
- dma_write(chan, XILINX_DMA_REG_PARK_PTR,
- config->park_frm <<
- XILINX_DMA_PARK_PTR_RD_REF_SHIFT);
- else
- dma_write(chan, XILINX_DMA_REG_PARK_PTR,
- config->park_frm <<
- XILINX_DMA_PARK_PTR_WR_REF_SHIFT);
- }
-
- /* Start the hardware */
- xilinx_dma_start(chan);
-
- if (chan->err)
- return;
-
- /* Start the transfer */
- if (chan->has_sg) {
- dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
- tail_segment->phys);
- } else {
- struct xilinx_vdma_tx_segment *segment, *last = NULL;
- int i = 0;
-
- if (chan->desc_submitcount < chan->num_frms)
- i = chan->desc_submitcount;
-
- list_for_each_entry(segment, &desc->segments, node) {
- if (chan->ext_addr)
- vdma_desc_write_64(chan,
- XILINX_VDMA_REG_START_ADDRESS_64(i++),
- segment->hw.buf_addr,
- segment->hw.buf_addr_msb);
- else
- vdma_desc_write(chan,
- XILINX_VDMA_REG_START_ADDRESS(i++),
- segment->hw.buf_addr);
-
- last = segment;
- }
-
- if (!last)
- return;
-
- /* HW expects these parameters to be same for one transaction */
- vdma_desc_write(chan, XILINX_DMA_REG_HSIZE, last->hw.hsize);
- vdma_desc_write(chan, XILINX_DMA_REG_FRMDLY_STRIDE,
- last->hw.stride);
- vdma_desc_write(chan, XILINX_DMA_REG_VSIZE, last->hw.vsize);
- }
-
- if (!chan->has_sg) {
- list_del(&desc->node);
- list_add_tail(&desc->node, &chan->active_list);
- chan->desc_submitcount++;
- chan->desc_pendingcount--;
- if (chan->desc_submitcount == chan->num_frms)
- chan->desc_submitcount = 0;
- } else {
- list_splice_tail_init(&chan->pending_list, &chan->active_list);
- chan->desc_pendingcount = 0;
- }
-}
-
-/**
- * xilinx_cdma_start_transfer - Starts cdma transfer
- * @chan: Driver specific channel struct pointer
- */
-static void xilinx_cdma_start_transfer(struct xilinx_dma_chan *chan)
-{
- struct xilinx_dma_tx_descriptor *head_desc, *tail_desc;
- struct xilinx_cdma_tx_segment *tail_segment;
- u32 ctrl_reg = dma_read(chan, XILINX_DMA_REG_DMACR);
-
- if (chan->err)
- return;
-
- if (list_empty(&chan->pending_list))
- return;
-
- head_desc = list_first_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor, node);
- tail_desc = list_last_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor, node);
- tail_segment = list_last_entry(&tail_desc->segments,
- struct xilinx_cdma_tx_segment, node);
-
- if (chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) {
- ctrl_reg &= ~XILINX_DMA_CR_COALESCE_MAX;
- ctrl_reg |= chan->desc_pendingcount <<
- XILINX_DMA_CR_COALESCE_SHIFT;
- dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, ctrl_reg);
- }
-
- if (chan->has_sg) {
- dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
- head_desc->async_tx.phys);
-
- /* Update tail ptr register which will start the transfer */
- dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
- tail_segment->phys);
- } else {
- /* In simple mode */
- struct xilinx_cdma_tx_segment *segment;
- struct xilinx_cdma_desc_hw *hw;
-
- segment = list_first_entry(&head_desc->segments,
- struct xilinx_cdma_tx_segment,
- node);
-
- hw = &segment->hw;
-
- dma_ctrl_write(chan, XILINX_CDMA_REG_SRCADDR, hw->src_addr);
- dma_ctrl_write(chan, XILINX_CDMA_REG_DSTADDR, hw->dest_addr);
-
- /* Start the transfer */
- dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
- hw->control & XILINX_DMA_MAX_TRANS_LEN);
- }
-
- list_splice_tail_init(&chan->pending_list, &chan->active_list);
- chan->desc_pendingcount = 0;
-}
-
-/**
- * xilinx_dma_start_transfer - Starts DMA transfer
- * @chan: Driver specific channel struct pointer
- */
-static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
-{
- struct xilinx_dma_tx_descriptor *head_desc, *tail_desc;
- struct xilinx_axidma_tx_segment *tail_segment, *old_head, *new_head;
- u32 reg;
-
- if (chan->err)
- return;
-
- if (list_empty(&chan->pending_list))
- return;
-
- /* If it is SG mode and hardware is busy, cannot submit */
- if (chan->has_sg && xilinx_dma_is_running(chan) &&
- !xilinx_dma_is_idle(chan)) {
- dev_dbg(chan->dev, "DMA controller still busy\n");
- return;
- }
-
- head_desc = list_first_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor, node);
- tail_desc = list_last_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor, node);
- tail_segment = list_last_entry(&tail_desc->segments,
- struct xilinx_axidma_tx_segment, node);
-
- old_head = list_first_entry(&head_desc->segments,
- struct xilinx_axidma_tx_segment, node);
- new_head = chan->seg_v;
- /* Copy Buffer Descriptor fields. */
- new_head->hw = old_head->hw;
-
- /* Swap and save new reserve */
- list_replace_init(&old_head->node, &new_head->node);
- chan->seg_v = old_head;
-
- tail_segment->hw.next_desc = chan->seg_v->phys;
- head_desc->async_tx.phys = new_head->phys;
-
- reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
-
- if (chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) {
- reg &= ~XILINX_DMA_CR_COALESCE_MAX;
- reg |= chan->desc_pendingcount <<
- XILINX_DMA_CR_COALESCE_SHIFT;
- dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
- }
-
- if (chan->has_sg)
- dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
- head_desc->async_tx.phys);
-
- xilinx_dma_start(chan);
-
- if (chan->err)
- return;
-
- /* Start the transfer */
- if (chan->has_sg) {
- dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
- tail_segment->phys);
- } else {
- struct xilinx_axidma_tx_segment *segment;
- struct xilinx_axidma_desc_hw *hw;
-
- segment = list_first_entry(&head_desc->segments,
- struct xilinx_axidma_tx_segment,
- node);
- hw = &segment->hw;
-
- dma_ctrl_write(chan, XILINX_DMA_REG_SRCDSTADDR, hw->buf_addr);
-
- /* Start the transfer */
- dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
- hw->control & XILINX_DMA_MAX_TRANS_LEN);
- }
-
- list_splice_tail_init(&chan->pending_list, &chan->active_list);
- chan->desc_pendingcount = 0;
-}
-
-/**
- * xilinx_dma_issue_pending - Issue pending transactions
- * @dchan: DMA channel
- */
-static void xilinx_dma_issue_pending(struct dma_chan *dchan)
-{
- struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
- unsigned long flags;
-
- spin_lock_irqsave(&chan->lock, flags);
- chan->start_transfer(chan);
- spin_unlock_irqrestore(&chan->lock, flags);
-}
-
-/**
- * xilinx_dma_complete_descriptor - Mark the active descriptor as complete
- * @chan : xilinx DMA channel
- *
- * CONTEXT: hardirq
- */
-static void xilinx_dma_complete_descriptor(struct xilinx_dma_chan *chan)
-{
- struct xilinx_dma_tx_descriptor *desc, *next;
-
- /* This function was invoked with lock held */
- if (list_empty(&chan->active_list))
- return;
-
- list_for_each_entry_safe(desc, next, &chan->active_list, node) {
- list_del(&desc->node);
- dma_cookie_complete(&desc->async_tx);
- list_add_tail(&desc->node, &chan->done_list);
- }
-}
-
-/**
- * xilinx_dma_reset - Reset DMA channel
- * @chan: Driver specific DMA channel
- *
- * Return: '0' on success and failure value on error
- */
-static int xilinx_dma_reset(struct xilinx_dma_chan *chan)
-{
- int err;
- u32 tmp;
-
- dma_ctrl_set(chan, XILINX_DMA_REG_DMACR, XILINX_DMA_DMACR_RESET);
-
- /* Wait for the hardware to finish reset */
- err = xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMACR, tmp,
- !(tmp & XILINX_DMA_DMACR_RESET), 0,
- XILINX_DMA_LOOP_COUNT);
-
- if (err) {
- dev_err(chan->dev, "reset timeout, cr %x, sr %x\n",
- dma_ctrl_read(chan, XILINX_DMA_REG_DMACR),
- dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
- return -ETIMEDOUT;
- }
-
- chan->err = false;
-
- return err;
-}
-
-/**
- * xilinx_dma_chan_reset - Reset DMA channel and enable interrupts
- * @chan: Driver specific DMA channel
- *
- * Return: '0' on success and failure value on error
- */
-static int xilinx_dma_chan_reset(struct xilinx_dma_chan *chan)
-{
- int err;
-
- /* Reset VDMA */
- err = xilinx_dma_reset(chan);
- if (err)
- return err;
-
- /* Enable interrupts */
- dma_ctrl_set(chan, XILINX_DMA_REG_DMACR,
- XILINX_DMA_DMAXR_ALL_IRQ_MASK);
-
- return 0;
-}
-
-/**
- * xilinx_dma_irq_handler - DMA Interrupt handler
- * @irq: IRQ number
- * @data: Pointer to the Xilinx DMA channel structure
- *
- * Return: IRQ_HANDLED/IRQ_NONE
- */
-static irqreturn_t xilinx_dma_irq_handler(int irq, void *data)
-{
- struct xilinx_dma_chan *chan = data;
- u32 status;
-
- /* Read the status and ack the interrupts. */
- status = dma_ctrl_read(chan, XILINX_DMA_REG_DMASR);
- if (!(status & XILINX_DMA_DMAXR_ALL_IRQ_MASK))
- return IRQ_NONE;
-
- dma_ctrl_write(chan, XILINX_DMA_REG_DMASR,
- status & XILINX_DMA_DMAXR_ALL_IRQ_MASK);
-
- if (status & XILINX_DMA_DMASR_ERR_IRQ) {
- /*
- * An error occurred. If C_FLUSH_ON_FSYNC is enabled and the
- * error is recoverable, ignore it. Otherwise flag the error.
- *
- * Only recoverable errors can be cleared in the DMASR register,
- * make sure not to write to other error bits to 1.
- */
- u32 errors = status & XILINX_DMA_DMASR_ALL_ERR_MASK;
-
- dma_ctrl_write(chan, XILINX_DMA_REG_DMASR,
- errors & XILINX_DMA_DMASR_ERR_RECOVER_MASK);
-
- if (!chan->flush_on_fsync ||
- (errors & ~XILINX_DMA_DMASR_ERR_RECOVER_MASK)) {
- dev_err(chan->dev,
- "Channel %p has errors %x, cdr %x tdr %x\n",
- chan, errors,
- dma_ctrl_read(chan, XILINX_DMA_REG_CURDESC),
- dma_ctrl_read(chan, XILINX_DMA_REG_TAILDESC));
- chan->err = true;
- }
- }
-
- if (status & XILINX_DMA_DMASR_DLY_CNT_IRQ) {
- /*
- * Device takes too long to do the transfer when user requires
- * responsiveness.
- */
- dev_dbg(chan->dev, "Inter-packet latency too long\n");
- }
-
- if (status & XILINX_DMA_DMASR_FRM_CNT_IRQ) {
- spin_lock(&chan->lock);
- xilinx_dma_complete_descriptor(chan);
- chan->start_transfer(chan);
- spin_unlock(&chan->lock);
- }
-
- tasklet_schedule(&chan->tasklet);
- return IRQ_HANDLED;
-}
-
-/**
- * append_desc_queue - Queuing descriptor
- * @chan: Driver specific dma channel
- * @desc: dma transaction descriptor
- */
-static void append_desc_queue(struct xilinx_dma_chan *chan,
- struct xilinx_dma_tx_descriptor *desc)
-{
- struct xilinx_vdma_tx_segment *tail_segment;
- struct xilinx_dma_tx_descriptor *tail_desc;
- struct xilinx_axidma_tx_segment *axidma_tail_segment;
- struct xilinx_cdma_tx_segment *cdma_tail_segment;
-
- if (list_empty(&chan->pending_list))
- goto append;
-
- /*
- * Add the hardware descriptor to the chain of hardware descriptors
- * that already exists in memory.
- */
- tail_desc = list_last_entry(&chan->pending_list,
- struct xilinx_dma_tx_descriptor, node);
- if (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
- tail_segment = list_last_entry(&tail_desc->segments,
- struct xilinx_vdma_tx_segment,
- node);
- tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
- } else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
- cdma_tail_segment = list_last_entry(&tail_desc->segments,
- struct xilinx_cdma_tx_segment,
- node);
- cdma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
- } else {
- axidma_tail_segment = list_last_entry(&tail_desc->segments,
- struct xilinx_axidma_tx_segment,
- node);
- axidma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
- }
-
- /*
- * Add the software descriptor and all children to the list
- * of pending transactions
- */
-append:
- list_add_tail(&desc->node, &chan->pending_list);
- chan->desc_pendingcount++;
-
- if (chan->has_sg && (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA)
- && unlikely(chan->desc_pendingcount > chan->num_frms)) {
- dev_dbg(chan->dev, "desc pendingcount is too high\n");
- chan->desc_pendingcount = chan->num_frms;
- }
-}
-
-/**
- * xilinx_dma_tx_submit - Submit DMA transaction
- * @tx: Async transaction descriptor
- *
- * Return: cookie value on success and failure value on error
- */
-static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
-{
- struct xilinx_dma_tx_descriptor *desc = to_dma_tx_descriptor(tx);
- struct xilinx_dma_chan *chan = to_xilinx_chan(tx->chan);
- dma_cookie_t cookie;
- unsigned long flags;
- int err;
-
- if (chan->err) {
- /*
- * If reset fails, need to hard reset the system.
- * Channel is no longer functional
- */
- err = xilinx_dma_chan_reset(chan);
- if (err < 0)
- return err;
- }
-
- spin_lock_irqsave(&chan->lock, flags);
-
- cookie = dma_cookie_assign(tx);
-
- /* Put this transaction onto the tail of the pending queue */
- append_desc_queue(chan, desc);
-
- spin_unlock_irqrestore(&chan->lock, flags);
-
- return cookie;
-}
-
-/**
- * xilinx_vdma_dma_prep_interleaved - prepare a descriptor for a
- * DMA_SLAVE transaction
- * @dchan: DMA channel
- * @xt: Interleaved template pointer
- * @flags: transfer ack flags
- *
- * Return: Async transaction descriptor on success and NULL on failure
- */
-static struct dma_async_tx_descriptor *
-xilinx_vdma_dma_prep_interleaved(struct dma_chan *dchan,
- struct dma_interleaved_template *xt,
- unsigned long flags)
-{
- struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
- struct xilinx_dma_tx_descriptor *desc;
- struct xilinx_vdma_tx_segment *segment, *prev = NULL;
- struct xilinx_vdma_desc_hw *hw;
-
- if (!is_slave_direction(xt->dir))
- return NULL;
-
- if (!xt->numf || !xt->sgl[0].size)
- return NULL;
-
- if (xt->frame_size != 1)
- return NULL;
-
- /* Allocate a transaction descriptor. */
- desc = xilinx_dma_alloc_tx_descriptor(chan);
- if (!desc)
- return NULL;
-
- dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
- desc->async_tx.tx_submit = xilinx_dma_tx_submit;
- async_tx_ack(&desc->async_tx);
-
- /* Allocate the link descriptor from DMA pool */
- segment = xilinx_vdma_alloc_tx_segment(chan);
- if (!segment)
- goto error;
-
- /* Fill in the hardware descriptor */
- hw = &segment->hw;
- hw->vsize = xt->numf;
- hw->hsize = xt->sgl[0].size;
- hw->stride = (xt->sgl[0].icg + xt->sgl[0].size) <<
- XILINX_DMA_FRMDLY_STRIDE_STRIDE_SHIFT;
- hw->stride |= chan->config.frm_dly <<
- XILINX_DMA_FRMDLY_STRIDE_FRMDLY_SHIFT;
-
- if (xt->dir != DMA_MEM_TO_DEV) {
- if (chan->ext_addr) {
- hw->buf_addr = lower_32_bits(xt->dst_start);
- hw->buf_addr_msb = upper_32_bits(xt->dst_start);
- } else {
- hw->buf_addr = xt->dst_start;
- }
- } else {
- if (chan->ext_addr) {
- hw->buf_addr = lower_32_bits(xt->src_start);
- hw->buf_addr_msb = upper_32_bits(xt->src_start);
- } else {
- hw->buf_addr = xt->src_start;
- }
- }
-
- /* Insert the segment into the descriptor segments list. */
- list_add_tail(&segment->node, &desc->segments);
-
- prev = segment;
-
- /* Link the last hardware descriptor with the first. */
- segment = list_first_entry(&desc->segments,
- struct xilinx_vdma_tx_segment, node);
- desc->async_tx.phys = segment->phys;
-
- return &desc->async_tx;
-
-error:
- xilinx_dma_free_tx_descriptor(chan, desc);
- return NULL;
-}
-
-/**
- * xilinx_cdma_prep_memcpy - prepare descriptors for a memcpy transaction
- * @dchan: DMA channel
- * @dma_dst: destination address
- * @dma_src: source address
- * @len: transfer length
- * @flags: transfer ack flags
- *
- * Return: Async transaction descriptor on success and NULL on failure
- */
-static struct dma_async_tx_descriptor *
-xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
- dma_addr_t dma_src, size_t len, unsigned long flags)
-{
- struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
- struct xilinx_dma_tx_descriptor *desc;
- struct xilinx_cdma_tx_segment *segment, *prev;
- struct xilinx_cdma_desc_hw *hw;
-
- if (!len || len > XILINX_DMA_MAX_TRANS_LEN)
- return NULL;
-
- desc = xilinx_dma_alloc_tx_descriptor(chan);
- if (!desc)
- return NULL;
-
- dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
- desc->async_tx.tx_submit = xilinx_dma_tx_submit;
-
- /* Allocate the link descriptor from DMA pool */
- segment = xilinx_cdma_alloc_tx_segment(chan);
- if (!segment)
- goto error;
-
- hw = &segment->hw;
- hw->control = len;
- hw->src_addr = dma_src;
- hw->dest_addr = dma_dst;
-
- /* Fill the previous next descriptor with current */
- prev = list_last_entry(&desc->segments,
- struct xilinx_cdma_tx_segment, node);
- prev->hw.next_desc = segment->phys;
-
- /* Insert the segment into the descriptor segments list. */
- list_add_tail(&segment->node, &desc->segments);
-
- prev = segment;
-
- /* Link the last hardware descriptor with the first. */
- segment = list_first_entry(&desc->segments,
- struct xilinx_cdma_tx_segment, node);
- desc->async_tx.phys = segment->phys;
- prev->hw.next_desc = segment->phys;
-
- return &desc->async_tx;
-
-error:
- xilinx_dma_free_tx_descriptor(chan, desc);
- return NULL;
-}
-
-/**
- * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
- * @dchan: DMA channel
- * @sgl: scatterlist to transfer to/from
- * @sg_len: number of entries in @scatterlist
- * @direction: DMA direction
- * @flags: transfer ack flags
- * @context: APP words of the descriptor
- *
- * Return: Async transaction descriptor on success and NULL on failure
- */
-static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
- struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
- enum dma_transfer_direction direction, unsigned long flags,
- void *context)
-{
- struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
- struct xilinx_dma_tx_descriptor *desc;
- struct xilinx_axidma_tx_segment *segment = NULL, *prev = NULL;
- u32 *app_w = (u32 *)context;
- struct scatterlist *sg;
- size_t copy;
- size_t sg_used;
- unsigned int i;
-
- if (!is_slave_direction(direction))
- return NULL;
-
- /* Allocate a transaction descriptor. */
- desc = xilinx_dma_alloc_tx_descriptor(chan);
- if (!desc)
- return NULL;
-
- dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
- desc->async_tx.tx_submit = xilinx_dma_tx_submit;
-
- /* Build transactions using information in the scatter gather list */
- for_each_sg(sgl, sg, sg_len, i) {
- sg_used = 0;
-
- /* Loop until the entire scatterlist entry is used */
- while (sg_used < sg_dma_len(sg)) {
- struct xilinx_axidma_desc_hw *hw;
-
- /* Get a free segment */
- segment = xilinx_axidma_alloc_tx_segment(chan);
- if (!segment)
- goto error;
-
- /*
- * Calculate the maximum number of bytes to transfer,
- * making sure it is less than the hw limit
- */
- copy = min_t(size_t, sg_dma_len(sg) - sg_used,
- XILINX_DMA_MAX_TRANS_LEN);
- hw = &segment->hw;
-
- /* Fill in the descriptor */
- hw->buf_addr = sg_dma_address(sg) + sg_used;
-
- hw->control = copy;
-
- if (chan->direction == DMA_MEM_TO_DEV) {
- if (app_w)
- memcpy(hw->app, app_w, sizeof(u32) *
- XILINX_DMA_NUM_APP_WORDS);
- }
-
- if (prev)
- prev->hw.next_desc = segment->phys;
-
- prev = segment;
- sg_used += copy;
-
- /*
- * Insert the segment into the descriptor segments
- * list.
- */
- list_add_tail(&segment->node, &desc->segments);
- }
- }
-
- segment = list_first_entry(&desc->segments,
- struct xilinx_axidma_tx_segment, node);
- desc->async_tx.phys = segment->phys;
- prev->hw.next_desc = segment->phys;
-
- /* For the last DMA_MEM_TO_DEV transfer, set EOP */
- if (chan->direction == DMA_MEM_TO_DEV) {
- segment->hw.control |= XILINX_DMA_BD_SOP;
- segment = list_last_entry(&desc->segments,
- struct xilinx_axidma_tx_segment,
- node);
- segment->hw.control |= XILINX_DMA_BD_EOP;
- }
-
- return &desc->async_tx;
-
-error:
- xilinx_dma_free_tx_descriptor(chan, desc);
- return NULL;
-}
-
-/**
- * xilinx_dma_terminate_all - Halt the channel and free descriptors
- * @chan: Driver specific DMA Channel pointer
- */
-static int xilinx_dma_terminate_all(struct dma_chan *dchan)
-{
- struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
-
- /* Halt the DMA engine */
- xilinx_dma_halt(chan);
-
- /* Remove and free all of the descriptors in the lists */
- xilinx_dma_free_descriptors(chan);
-
- return 0;
-}
-
-/**
- * xilinx_dma_channel_set_config - Configure VDMA channel
- * Run-time configuration for Axi VDMA, supports:
- * . halt the channel
- * . configure interrupt coalescing and inter-packet delay threshold
- * . start/stop parking
- * . enable genlock
- *
- * @dchan: DMA channel
- * @cfg: VDMA device configuration pointer
- *
- * Return: '0' on success and failure value on error
- */
-int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
- struct xilinx_vdma_config *cfg)
-{
- struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
- u32 dmacr;
-
- if (cfg->reset)
- return xilinx_dma_chan_reset(chan);
-
- dmacr = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
-
- chan->config.frm_dly = cfg->frm_dly;
- chan->config.park = cfg->park;
-
- /* genlock settings */
- chan->config.gen_lock = cfg->gen_lock;
- chan->config.master = cfg->master;
-
- if (cfg->gen_lock && chan->genlock) {
- dmacr |= XILINX_DMA_DMACR_GENLOCK_EN;
- dmacr |= cfg->master << XILINX_DMA_DMACR_MASTER_SHIFT;
- }
-
- chan->config.frm_cnt_en = cfg->frm_cnt_en;
- if (cfg->park)
- chan->config.park_frm = cfg->park_frm;
- else
- chan->config.park_frm = -1;
-
- chan->config.coalesc = cfg->coalesc;
- chan->config.delay = cfg->delay;
-
- if (cfg->coalesc <= XILINX_DMA_DMACR_FRAME_COUNT_MAX) {
- dmacr |= cfg->coalesc << XILINX_DMA_DMACR_FRAME_COUNT_SHIFT;
- chan->config.coalesc = cfg->coalesc;
- }
-
- if (cfg->delay <= XILINX_DMA_DMACR_DELAY_MAX) {
- dmacr |= cfg->delay << XILINX_DMA_DMACR_DELAY_SHIFT;
- chan->config.delay = cfg->delay;
- }
-
- /* FSync Source selection */
- dmacr &= ~XILINX_DMA_DMACR_FSYNCSRC_MASK;
- dmacr |= cfg->ext_fsync << XILINX_DMA_DMACR_FSYNCSRC_SHIFT;
-
- dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, dmacr);
-
- return 0;
-}
-EXPORT_SYMBOL(xilinx_vdma_channel_set_config);
-
-/* -----------------------------------------------------------------------------
- * Probe and remove
- */
-
-/**
- * xilinx_dma_chan_remove - Per Channel remove function
- * @chan: Driver specific DMA channel
- */
-static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan)
-{
- /* Disable all interrupts */
- dma_ctrl_clr(chan, XILINX_DMA_REG_DMACR,
- XILINX_DMA_DMAXR_ALL_IRQ_MASK);
-
- if (chan->irq > 0)
- free_irq(chan->irq, chan);
-
- tasklet_kill(&chan->tasklet);
-
- list_del(&chan->common.device_node);
-}
-
-static int axidma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
- struct clk **tx_clk, struct clk **rx_clk,
- struct clk **sg_clk, struct clk **tmp_clk)
-{
- int err;
-
- *tmp_clk = NULL;
-
- *axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
- if (IS_ERR(*axi_clk)) {
- err = PTR_ERR(*axi_clk);
- dev_err(&pdev->dev, "failed to get axi_aclk (%u)\n", err);
- return err;
- }
-
- *tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk");
- if (IS_ERR(*tx_clk))
- *tx_clk = NULL;
-
- *rx_clk = devm_clk_get(&pdev->dev, "m_axi_s2mm_aclk");
- if (IS_ERR(*rx_clk))
- *rx_clk = NULL;
-
- *sg_clk = devm_clk_get(&pdev->dev, "m_axi_sg_aclk");
- if (IS_ERR(*sg_clk))
- *sg_clk = NULL;
-
- err = clk_prepare_enable(*axi_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
- return err;
- }
-
- err = clk_prepare_enable(*tx_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
- goto err_disable_axiclk;
- }
-
- err = clk_prepare_enable(*rx_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable rx_clk (%u)\n", err);
- goto err_disable_txclk;
- }
-
- err = clk_prepare_enable(*sg_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable sg_clk (%u)\n", err);
- goto err_disable_rxclk;
- }
-
- return 0;
-
-err_disable_rxclk:
- clk_disable_unprepare(*rx_clk);
-err_disable_txclk:
- clk_disable_unprepare(*tx_clk);
-err_disable_axiclk:
- clk_disable_unprepare(*axi_clk);
-
- return err;
-}
-
-static int axicdma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
- struct clk **dev_clk, struct clk **tmp_clk,
- struct clk **tmp1_clk, struct clk **tmp2_clk)
-{
- int err;
-
- *tmp_clk = NULL;
- *tmp1_clk = NULL;
- *tmp2_clk = NULL;
-
- *axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
- if (IS_ERR(*axi_clk)) {
- err = PTR_ERR(*axi_clk);
- dev_err(&pdev->dev, "failed to get axi_clk (%u)\n", err);
- return err;
- }
-
- *dev_clk = devm_clk_get(&pdev->dev, "m_axi_aclk");
- if (IS_ERR(*dev_clk)) {
- err = PTR_ERR(*dev_clk);
- dev_err(&pdev->dev, "failed to get dev_clk (%u)\n", err);
- return err;
- }
-
- err = clk_prepare_enable(*axi_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
- return err;
- }
-
- err = clk_prepare_enable(*dev_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable dev_clk (%u)\n", err);
- goto err_disable_axiclk;
- }
-
- return 0;
-
-err_disable_axiclk:
- clk_disable_unprepare(*axi_clk);
-
- return err;
-}
-
-static int axivdma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
- struct clk **tx_clk, struct clk **txs_clk,
- struct clk **rx_clk, struct clk **rxs_clk)
-{
- int err;
-
- *axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
- if (IS_ERR(*axi_clk)) {
- err = PTR_ERR(*axi_clk);
- dev_err(&pdev->dev, "failed to get axi_aclk (%u)\n", err);
- return err;
- }
-
- *tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk");
- if (IS_ERR(*tx_clk))
- *tx_clk = NULL;
-
- *txs_clk = devm_clk_get(&pdev->dev, "m_axis_mm2s_aclk");
- if (IS_ERR(*txs_clk))
- *txs_clk = NULL;
-
- *rx_clk = devm_clk_get(&pdev->dev, "m_axi_s2mm_aclk");
- if (IS_ERR(*rx_clk))
- *rx_clk = NULL;
-
- *rxs_clk = devm_clk_get(&pdev->dev, "s_axis_s2mm_aclk");
- if (IS_ERR(*rxs_clk))
- *rxs_clk = NULL;
-
- err = clk_prepare_enable(*axi_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
- return err;
- }
-
- err = clk_prepare_enable(*tx_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
- goto err_disable_axiclk;
- }
-
- err = clk_prepare_enable(*txs_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable txs_clk (%u)\n", err);
- goto err_disable_txclk;
- }
-
- err = clk_prepare_enable(*rx_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable rx_clk (%u)\n", err);
- goto err_disable_txsclk;
- }
-
- err = clk_prepare_enable(*rxs_clk);
- if (err) {
- dev_err(&pdev->dev, "failed to enable rxs_clk (%u)\n", err);
- goto err_disable_rxclk;
- }
-
- return 0;
-
-err_disable_rxclk:
- clk_disable_unprepare(*rx_clk);
-err_disable_txsclk:
- clk_disable_unprepare(*txs_clk);
-err_disable_txclk:
- clk_disable_unprepare(*tx_clk);
-err_disable_axiclk:
- clk_disable_unprepare(*axi_clk);
-
- return err;
-}
-
-static void xdma_disable_allclks(struct xilinx_dma_device *xdev)
-{
- clk_disable_unprepare(xdev->rxs_clk);
- clk_disable_unprepare(xdev->rx_clk);
- clk_disable_unprepare(xdev->txs_clk);
- clk_disable_unprepare(xdev->tx_clk);
- clk_disable_unprepare(xdev->axi_clk);
-}
-
-/**
- * xilinx_dma_chan_probe - Per Channel Probing
- * It get channel features from the device tree entry and
- * initialize special channel handling routines
- *
- * @xdev: Driver specific device structure
- * @node: Device node
- *
- * Return: '0' on success and failure value on error
- */
-static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
- struct device_node *node)
-{
- struct xilinx_dma_chan *chan;
- bool has_dre = false;
- u32 value, width;
- int err;
-
- /* Allocate and initialize the channel structure */
- chan = devm_kzalloc(xdev->dev, sizeof(*chan), GFP_KERNEL);
- if (!chan)
- return -ENOMEM;
-
- chan->dev = xdev->dev;
- chan->xdev = xdev;
- chan->has_sg = xdev->has_sg;
- chan->desc_pendingcount = 0x0;
- chan->ext_addr = xdev->ext_addr;
-
- spin_lock_init(&chan->lock);
- INIT_LIST_HEAD(&chan->pending_list);
- INIT_LIST_HEAD(&chan->done_list);
- INIT_LIST_HEAD(&chan->active_list);
-
- /* Retrieve the channel properties from the device tree */
- has_dre = of_property_read_bool(node, "xlnx,include-dre");
-
- chan->genlock = of_property_read_bool(node, "xlnx,genlock-mode");
-
- err = of_property_read_u32(node, "xlnx,datawidth", &value);
- if (err) {
- dev_err(xdev->dev, "missing xlnx,datawidth property\n");
- return err;
- }
- width = value >> 3; /* Convert bits to bytes */
-
- /* If data width is greater than 8 bytes, DRE is not in hw */
- if (width > 8)
- has_dre = false;
-
- if (!has_dre)
- xdev->common.copy_align = fls(width - 1);
-
- if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel")) {
- chan->direction = DMA_MEM_TO_DEV;
- chan->id = 0;
-
- chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
- if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
- chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
-
- if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
- xdev->flush_on_fsync == XILINX_DMA_FLUSH_MM2S)
- chan->flush_on_fsync = true;
- }
- } else if (of_device_is_compatible(node,
- "xlnx,axi-vdma-s2mm-channel")) {
- chan->direction = DMA_DEV_TO_MEM;
- chan->id = 1;
-
- chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
- if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
- chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
-
- if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
- xdev->flush_on_fsync == XILINX_DMA_FLUSH_S2MM)
- chan->flush_on_fsync = true;
- }
- } else {
- dev_err(xdev->dev, "Invalid channel compatible node\n");
- return -EINVAL;
- }
-
- /* Request the interrupt */
- chan->irq = irq_of_parse_and_map(node, 0);
- err = request_irq(chan->irq, xilinx_dma_irq_handler, IRQF_SHARED,
- "xilinx-dma-controller", chan);
- if (err) {
- dev_err(xdev->dev, "unable to request IRQ %d\n", chan->irq);
- return err;
- }
-
- if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
- chan->start_transfer = xilinx_dma_start_transfer;
- else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA)
- chan->start_transfer = xilinx_cdma_start_transfer;
- else
- chan->start_transfer = xilinx_vdma_start_transfer;
-
- /* Initialize the tasklet */
- tasklet_init(&chan->tasklet, xilinx_dma_do_tasklet,
- (unsigned long)chan);
-
- /*
- * Initialize the DMA channel and add it to the DMA engine channels
- * list.
- */
- chan->common.device = &xdev->common;
-
- list_add_tail(&chan->common.device_node, &xdev->common.channels);
- xdev->chan[chan->id] = chan;
-
- /* Reset the channel */
- err = xilinx_dma_chan_reset(chan);
- if (err < 0) {
- dev_err(xdev->dev, "Reset channel failed\n");
- return err;
- }
-
- return 0;
-}
-
-/**
- * of_dma_xilinx_xlate - Translation function
- * @dma_spec: Pointer to DMA specifier as found in the device tree
- * @ofdma: Pointer to DMA controller data
- *
- * Return: DMA channel pointer on success and NULL on error
- */
-static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
- struct of_dma *ofdma)
-{
- struct xilinx_dma_device *xdev = ofdma->of_dma_data;
- int chan_id = dma_spec->args[0];
-
- if (chan_id >= XILINX_DMA_MAX_CHANS_PER_DEVICE || !xdev->chan[chan_id])
- return NULL;
-
- return dma_get_slave_channel(&xdev->chan[chan_id]->common);
-}
-
-static const struct xilinx_dma_config axidma_config = {
- .dmatype = XDMA_TYPE_AXIDMA,
- .clk_init = axidma_clk_init,
-};
-
-static const struct xilinx_dma_config axicdma_config = {
- .dmatype = XDMA_TYPE_CDMA,
- .clk_init = axicdma_clk_init,
-};
-
-static const struct xilinx_dma_config axivdma_config = {
- .dmatype = XDMA_TYPE_VDMA,
- .clk_init = axivdma_clk_init,
-};
-
-static const struct of_device_id xilinx_dma_of_ids[] = {
- { .compatible = "xlnx,axi-dma-1.00.a", .data = &axidma_config },
- { .compatible = "xlnx,axi-cdma-1.00.a", .data = &axicdma_config },
- { .compatible = "xlnx,axi-vdma-1.00.a", .data = &axivdma_config },
- {}
-};
-MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
-
-/**
- * xilinx_dma_probe - Driver probe function
- * @pdev: Pointer to the platform_device structure
- *
- * Return: '0' on success and failure value on error
- */
-static int xilinx_dma_probe(struct platform_device *pdev)
-{
- int (*clk_init)(struct platform_device *, struct clk **, struct clk **,
- struct clk **, struct clk **, struct clk **)
- = axivdma_clk_init;
- struct device_node *node = pdev->dev.of_node;
- struct xilinx_dma_device *xdev;
- struct device_node *child, *np = pdev->dev.of_node;
- struct resource *io;
- u32 num_frames, addr_width;
- int i, err;
-
- /* Allocate and initialize the DMA engine structure */
- xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
- if (!xdev)
- return -ENOMEM;
-
- xdev->dev = &pdev->dev;
- if (np) {
- const struct of_device_id *match;
-
- match = of_match_node(xilinx_dma_of_ids, np);
- if (match && match->data) {
- xdev->dma_config = match->data;
- clk_init = xdev->dma_config->clk_init;
- }
- }
-
- err = clk_init(pdev, &xdev->axi_clk, &xdev->tx_clk, &xdev->txs_clk,
- &xdev->rx_clk, &xdev->rxs_clk);
- if (err)
- return err;
-
- /* Request and map I/O memory */
- io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- xdev->regs = devm_ioremap_resource(&pdev->dev, io);
- if (IS_ERR(xdev->regs))
- return PTR_ERR(xdev->regs);
-
- /* Retrieve the DMA engine properties from the device tree */
- xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
-
- if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
- err = of_property_read_u32(node, "xlnx,num-fstores",
- &num_frames);
- if (err < 0) {
- dev_err(xdev->dev,
- "missing xlnx,num-fstores property\n");
- return err;
- }
-
- err = of_property_read_u32(node, "xlnx,flush-fsync",
- &xdev->flush_on_fsync);
- if (err < 0)
- dev_warn(xdev->dev,
- "missing xlnx,flush-fsync property\n");
- }
-
- err = of_property_read_u32(node, "xlnx,addrwidth", &addr_width);
- if (err < 0)
- dev_warn(xdev->dev, "missing xlnx,addrwidth property\n");
-
- if (addr_width > 32)
- xdev->ext_addr = true;
- else
- xdev->ext_addr = false;
-
- /* Set the dma mask bits */
- dma_set_mask(xdev->dev, DMA_BIT_MASK(addr_width));
-
- /* Initialize the DMA engine */
- xdev->common.dev = &pdev->dev;
-
- INIT_LIST_HEAD(&xdev->common.channels);
- if (!(xdev->dma_config->dmatype == XDMA_TYPE_CDMA)) {
- dma_cap_set(DMA_SLAVE, xdev->common.cap_mask);
- dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask);
- }
-
- xdev->common.device_alloc_chan_resources =
- xilinx_dma_alloc_chan_resources;
- xdev->common.device_free_chan_resources =
- xilinx_dma_free_chan_resources;
- xdev->common.device_terminate_all = xilinx_dma_terminate_all;
- xdev->common.device_tx_status = xilinx_dma_tx_status;
- xdev->common.device_issue_pending = xilinx_dma_issue_pending;
- if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
- xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
- /* Residue calculation is supported by only AXI DMA */
- xdev->common.residue_granularity =
- DMA_RESIDUE_GRANULARITY_SEGMENT;
- } else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
- dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask);
- xdev->common.device_prep_dma_memcpy = xilinx_cdma_prep_memcpy;
- } else {
- xdev->common.device_prep_interleaved_dma =
- xilinx_vdma_dma_prep_interleaved;
- }
-
- platform_set_drvdata(pdev, xdev);
-
- /* Initialize the channels */
- for_each_child_of_node(node, child) {
- err = xilinx_dma_chan_probe(xdev, child);
- if (err < 0)
- goto disable_clks;
- }
-
- if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
- for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
- if (xdev->chan[i])
- xdev->chan[i]->num_frms = num_frames;
- }
-
- /* Register the DMA engine with the core */
- dma_async_device_register(&xdev->common);
-
- err = of_dma_controller_register(node, of_dma_xilinx_xlate,
- xdev);
- if (err < 0) {
- dev_err(&pdev->dev, "Unable to register DMA to DT\n");
- dma_async_device_unregister(&xdev->common);
- goto error;
- }
-
- dev_info(&pdev->dev, "Xilinx AXI VDMA Engine Driver Probed!!\n");
-
- return 0;
-
-disable_clks:
- xdma_disable_allclks(xdev);
-error:
- for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
- if (xdev->chan[i])
- xilinx_dma_chan_remove(xdev->chan[i]);
-
- return err;
-}
-
-/**
- * xilinx_dma_remove - Driver remove function
- * @pdev: Pointer to the platform_device structure
- *
- * Return: Always '0'
- */
-static int xilinx_dma_remove(struct platform_device *pdev)
-{
- struct xilinx_dma_device *xdev = platform_get_drvdata(pdev);
- int i;
-
- of_dma_controller_free(pdev->dev.of_node);
-
- dma_async_device_unregister(&xdev->common);
-
- for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
- if (xdev->chan[i])
- xilinx_dma_chan_remove(xdev->chan[i]);
-
- xdma_disable_allclks(xdev);
-
- return 0;
-}
-
-static struct platform_driver xilinx_vdma_driver = {
- .driver = {
- .name = "xilinx-vdma",
- .of_match_table = xilinx_dma_of_ids,
- },
- .probe = xilinx_dma_probe,
- .remove = xilinx_dma_remove,
-};
-
-module_platform_driver(xilinx_vdma_driver);
-
-MODULE_AUTHOR("Xilinx, Inc.");
-MODULE_DESCRIPTION("Xilinx VDMA driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_smumgr.h b/drivers/gpu/drm/amd/amdgpu/iceland_smumgr.h
deleted file mode 100644
index 1e0769e11..000000000
--- a/drivers/gpu/drm/amd/amdgpu/iceland_smumgr.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2014 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef ICELAND_SMUMGR_H
-#define ICELAND_SMUMGR_H
-
-#include "ppsmc.h"
-
-extern int iceland_smu_init(struct amdgpu_device *adev);
-extern int iceland_smu_fini(struct amdgpu_device *adev);
-extern int iceland_smu_start(struct amdgpu_device *adev);
-
-struct iceland_smu_private_data
-{
- uint8_t *header;
- uint8_t *mec_image;
- uint32_t header_addr_high;
- uint32_t header_addr_low;
-};
-
-#endif
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c
deleted file mode 100644
index a02112ba1..000000000
--- a/drivers/gpu/drm/i2c/adv7511.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-/*
- * Analog Devices ADV7511 HDMI transmitter driver
- *
- * Copyright 2012 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#include <linux/device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/regmap.h>
-#include <linux/slab.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_encoder_slave.h>
-
-#include "adv7511.h"
-
-struct adv7511 {
- struct i2c_client *i2c_main;
- struct i2c_client *i2c_edid;
-
- struct regmap *regmap;
- struct regmap *packet_memory_regmap;
- enum drm_connector_status status;
- bool powered;
-
- unsigned int f_tmds;
-
- unsigned int current_edid_segment;
- uint8_t edid_buf[256];
- bool edid_read;
-
- wait_queue_head_t wq;
- struct drm_encoder *encoder;
-
- bool embedded_sync;
- enum adv7511_sync_polarity vsync_polarity;
- enum adv7511_sync_polarity hsync_polarity;
- bool rgb;
-
- struct edid *edid;
-
- struct gpio_desc *gpio_pd;
-};
-
-static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder)
-{
- return to_encoder_slave(encoder)->slave_priv;
-}
-
-/* ADI recommended values for proper operation. */
-static const struct reg_sequence adv7511_fixed_registers[] = {
- { 0x98, 0x03 },
- { 0x9a, 0xe0 },
- { 0x9c, 0x30 },
- { 0x9d, 0x61 },
- { 0xa2, 0xa4 },
- { 0xa3, 0xa4 },
- { 0xe0, 0xd0 },
- { 0xf9, 0x00 },
- { 0x55, 0x02 },
-};
-
-/* -----------------------------------------------------------------------------
- * Register access
- */
-
-static const uint8_t adv7511_register_defaults[] = {
- 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */
- 0x00, 0x00, 0x01, 0x0e, 0xbc, 0x18, 0x01, 0x13,
- 0x25, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */
- 0x46, 0x62, 0x04, 0xa8, 0x00, 0x00, 0x1c, 0x84,
- 0x1c, 0xbf, 0x04, 0xa8, 0x1e, 0x70, 0x02, 0x1e, /* 20 */
- 0x00, 0x00, 0x04, 0xa8, 0x08, 0x12, 0x1b, 0xac,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 */
- 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
- 0x00, 0x50, 0x90, 0x7e, 0x79, 0x70, 0x00, 0x00, /* 40 */
- 0x00, 0xa8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, /* 50 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 60 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 90 */
- 0x0b, 0x02, 0x00, 0x18, 0x5a, 0x60, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00, /* a0 */
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x14,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c0 */
- 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04,
- 0x30, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* d0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01,
- 0x80, 0x75, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* e0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00, /* f0 */
- 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static bool adv7511_register_volatile(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case ADV7511_REG_CHIP_REVISION:
- case ADV7511_REG_SPDIF_FREQ:
- case ADV7511_REG_CTS_AUTOMATIC1:
- case ADV7511_REG_CTS_AUTOMATIC2:
- case ADV7511_REG_VIC_DETECTED:
- case ADV7511_REG_VIC_SEND:
- case ADV7511_REG_AUX_VIC_DETECTED:
- case ADV7511_REG_STATUS:
- case ADV7511_REG_GC(1):
- case ADV7511_REG_INT(0):
- case ADV7511_REG_INT(1):
- case ADV7511_REG_PLL_STATUS:
- case ADV7511_REG_AN(0):
- case ADV7511_REG_AN(1):
- case ADV7511_REG_AN(2):
- case ADV7511_REG_AN(3):
- case ADV7511_REG_AN(4):
- case ADV7511_REG_AN(5):
- case ADV7511_REG_AN(6):
- case ADV7511_REG_AN(7):
- case ADV7511_REG_HDCP_STATUS:
- case ADV7511_REG_BCAPS:
- case ADV7511_REG_BKSV(0):
- case ADV7511_REG_BKSV(1):
- case ADV7511_REG_BKSV(2):
- case ADV7511_REG_BKSV(3):
- case ADV7511_REG_BKSV(4):
- case ADV7511_REG_DDC_STATUS:
- case ADV7511_REG_EDID_READ_CTRL:
- case ADV7511_REG_BSTATUS(0):
- case ADV7511_REG_BSTATUS(1):
- case ADV7511_REG_CHIP_ID_HIGH:
- case ADV7511_REG_CHIP_ID_LOW:
- return true;
- }
-
- return false;
-}
-
-static const struct regmap_config adv7511_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
-
- .max_register = 0xff,
- .cache_type = REGCACHE_RBTREE,
- .reg_defaults_raw = adv7511_register_defaults,
- .num_reg_defaults_raw = ARRAY_SIZE(adv7511_register_defaults),
-
- .volatile_reg = adv7511_register_volatile,
-};
-
-/* -----------------------------------------------------------------------------
- * Hardware configuration
- */
-
-static void adv7511_set_colormap(struct adv7511 *adv7511, bool enable,
- const uint16_t *coeff,
- unsigned int scaling_factor)
-{
- unsigned int i;
-
- regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1),
- ADV7511_CSC_UPDATE_MODE, ADV7511_CSC_UPDATE_MODE);
-
- if (enable) {
- for (i = 0; i < 12; ++i) {
- regmap_update_bits(adv7511->regmap,
- ADV7511_REG_CSC_UPPER(i),
- 0x1f, coeff[i] >> 8);
- regmap_write(adv7511->regmap,
- ADV7511_REG_CSC_LOWER(i),
- coeff[i] & 0xff);
- }
- }
-
- if (enable)
- regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0),
- 0xe0, 0x80 | (scaling_factor << 5));
- else
- regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0),
- 0x80, 0x00);
-
- regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1),
- ADV7511_CSC_UPDATE_MODE, 0);
-}
-
-static int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet)
-{
- if (packet & 0xff)
- regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0,
- packet, 0xff);
-
- if (packet & 0xff00) {
- packet >>= 8;
- regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
- packet, 0xff);
- }
-
- return 0;
-}
-
-static int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet)
-{
- if (packet & 0xff)
- regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0,
- packet, 0x00);
-
- if (packet & 0xff00) {
- packet >>= 8;
- regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
- packet, 0x00);
- }
-
- return 0;
-}
-
-/* Coefficients for adv7511 color space conversion */
-static const uint16_t adv7511_csc_ycbcr_to_rgb[] = {
- 0x0734, 0x04ad, 0x0000, 0x1c1b,
- 0x1ddc, 0x04ad, 0x1f24, 0x0135,
- 0x0000, 0x04ad, 0x087c, 0x1b77,
-};
-
-static void adv7511_set_config_csc(struct adv7511 *adv7511,
- struct drm_connector *connector,
- bool rgb)
-{
- struct adv7511_video_config config;
- bool output_format_422, output_format_ycbcr;
- unsigned int mode;
- uint8_t infoframe[17];
-
- if (adv7511->edid)
- config.hdmi_mode = drm_detect_hdmi_monitor(adv7511->edid);
- else
- config.hdmi_mode = false;
-
- hdmi_avi_infoframe_init(&config.avi_infoframe);
-
- config.avi_infoframe.scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
-
- if (rgb) {
- config.csc_enable = false;
- config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
- } else {
- config.csc_scaling_factor = ADV7511_CSC_SCALING_4;
- config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;
-
- if ((connector->display_info.color_formats &
- DRM_COLOR_FORMAT_YCRCB422) &&
- config.hdmi_mode) {
- config.csc_enable = false;
- config.avi_infoframe.colorspace =
- HDMI_COLORSPACE_YUV422;
- } else {
- config.csc_enable = true;
- config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
- }
- }
-
- if (config.hdmi_mode) {
- mode = ADV7511_HDMI_CFG_MODE_HDMI;
-
- switch (config.avi_infoframe.colorspace) {
- case HDMI_COLORSPACE_YUV444:
- output_format_422 = false;
- output_format_ycbcr = true;
- break;
- case HDMI_COLORSPACE_YUV422:
- output_format_422 = true;
- output_format_ycbcr = true;
- break;
- default:
- output_format_422 = false;
- output_format_ycbcr = false;
- break;
- }
- } else {
- mode = ADV7511_HDMI_CFG_MODE_DVI;
- output_format_422 = false;
- output_format_ycbcr = false;
- }
-
- adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
-
- adv7511_set_colormap(adv7511, config.csc_enable,
- config.csc_coefficents,
- config.csc_scaling_factor);
-
- regmap_update_bits(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, 0x81,
- (output_format_422 << 7) | output_format_ycbcr);
-
- regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
- ADV7511_HDMI_CFG_MODE_MASK, mode);
-
- hdmi_avi_infoframe_pack(&config.avi_infoframe, infoframe,
- sizeof(infoframe));
-
- /* The AVI infoframe id is not configurable */
- regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
- infoframe + 1, sizeof(infoframe) - 1);
-
- adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
-}
-
-static void adv7511_set_link_config(struct adv7511 *adv7511,
- const struct adv7511_link_config *config)
-{
- /*
- * The input style values documented in the datasheet don't match the
- * hardware register field values :-(
- */
- static const unsigned int input_styles[4] = { 0, 2, 1, 3 };
-
- unsigned int clock_delay;
- unsigned int color_depth;
- unsigned int input_id;
-
- clock_delay = (config->clock_delay + 1200) / 400;
- color_depth = config->input_color_depth == 8 ? 3
- : (config->input_color_depth == 10 ? 1 : 2);
-
- /* TODO Support input ID 6 */
- if (config->input_colorspace != HDMI_COLORSPACE_YUV422)
- input_id = config->input_clock == ADV7511_INPUT_CLOCK_DDR
- ? 5 : 0;
- else if (config->input_clock == ADV7511_INPUT_CLOCK_DDR)
- input_id = config->embedded_sync ? 8 : 7;
- else if (config->input_clock == ADV7511_INPUT_CLOCK_2X)
- input_id = config->embedded_sync ? 4 : 3;
- else
- input_id = config->embedded_sync ? 2 : 1;
-
- regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG, 0xf,
- input_id);
- regmap_update_bits(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, 0x7e,
- (color_depth << 4) |
- (input_styles[config->input_style] << 2));
- regmap_write(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG2,
- config->input_justification << 3);
- regmap_write(adv7511->regmap, ADV7511_REG_TIMING_GEN_SEQ,
- config->sync_pulse << 2);
-
- regmap_write(adv7511->regmap, 0xba, clock_delay << 5);
-
- adv7511->embedded_sync = config->embedded_sync;
- adv7511->hsync_polarity = config->hsync_polarity;
- adv7511->vsync_polarity = config->vsync_polarity;
- adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB;
-}
-
-static void adv7511_power_on(struct adv7511 *adv7511)
-{
- adv7511->current_edid_segment = -1;
-
- regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
- ADV7511_POWER_POWER_DOWN, 0);
- if (adv7511->i2c_main->irq) {
- /*
- * Documentation says the INT_ENABLE registers are reset in
- * POWER_DOWN mode. My 7511w preserved the bits, however.
- * Still, let's be safe and stick to the documentation.
- */
- regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
- ADV7511_INT0_EDID_READY);
- regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
- ADV7511_INT1_DDC_ERROR);
- }
-
- /*
- * Per spec it is allowed to pulse the HPD signal to indicate that the
- * EDID information has changed. Some monitors do this when they wakeup
- * from standby or are enabled. When the HPD goes low the adv7511 is
- * reset and the outputs are disabled which might cause the monitor to
- * go to standby again. To avoid this we ignore the HPD pin for the
- * first few seconds after enabling the output.
- */
- regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
- ADV7511_REG_POWER2_HPD_SRC_MASK,
- ADV7511_REG_POWER2_HPD_SRC_NONE);
-
- /*
- * Most of the registers are reset during power down or when HPD is low.
- */
- regcache_sync(adv7511->regmap);
-
- adv7511->powered = true;
-}
-
-static void adv7511_power_off(struct adv7511 *adv7511)
-{
- /* TODO: setup additional power down modes */
- regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
- ADV7511_POWER_POWER_DOWN,
- ADV7511_POWER_POWER_DOWN);
- regcache_mark_dirty(adv7511->regmap);
-
- adv7511->powered = false;
-}
-
-/* -----------------------------------------------------------------------------
- * Interrupt and hotplug detection
- */
-
-static bool adv7511_hpd(struct adv7511 *adv7511)
-{
- unsigned int irq0;
- int ret;
-
- ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
- if (ret < 0)
- return false;
-
- if (irq0 & ADV7511_INT0_HPD) {
- regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
- ADV7511_INT0_HPD);
- return true;
- }
-
- return false;
-}
-
-static int adv7511_irq_process(struct adv7511 *adv7511)
-{
- unsigned int irq0, irq1;
- int ret;
-
- ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
- if (ret < 0)
- return ret;
-
- ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1);
- if (ret < 0)
- return ret;
-
- regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
- regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
-
- if (irq0 & ADV7511_INT0_HPD && adv7511->encoder)
- drm_helper_hpd_irq_event(adv7511->encoder->dev);
-
- if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
- adv7511->edid_read = true;
-
- if (adv7511->i2c_main->irq)
- wake_up_all(&adv7511->wq);
- }
-
- return 0;
-}
-
-static irqreturn_t adv7511_irq_handler(int irq, void *devid)
-{
- struct adv7511 *adv7511 = devid;
- int ret;
-
- ret = adv7511_irq_process(adv7511);
- return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
-}
-
-/* -----------------------------------------------------------------------------
- * EDID retrieval
- */
-
-static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout)
-{
- int ret;
-
- if (adv7511->i2c_main->irq) {
- ret = wait_event_interruptible_timeout(adv7511->wq,
- adv7511->edid_read, msecs_to_jiffies(timeout));
- } else {
- for (; timeout > 0; timeout -= 25) {
- ret = adv7511_irq_process(adv7511);
- if (ret < 0)
- break;
-
- if (adv7511->edid_read)
- break;
-
- msleep(25);
- }
- }
-
- return adv7511->edid_read ? 0 : -EIO;
-}
-
-static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
- size_t len)
-{
- struct adv7511 *adv7511 = data;
- struct i2c_msg xfer[2];
- uint8_t offset;
- unsigned int i;
- int ret;
-
- if (len > 128)
- return -EINVAL;
-
- if (adv7511->current_edid_segment != block / 2) {
- unsigned int status;
-
- ret = regmap_read(adv7511->regmap, ADV7511_REG_DDC_STATUS,
- &status);
- if (ret < 0)
- return ret;
-
- if (status != 2) {
- adv7511->edid_read = false;
- regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT,
- block);
- ret = adv7511_wait_for_edid(adv7511, 200);
- if (ret < 0)
- return ret;
- }
-
- /* Break this apart, hopefully more I2C controllers will
- * support 64 byte transfers than 256 byte transfers
- */
-
- xfer[0].addr = adv7511->i2c_edid->addr;
- xfer[0].flags = 0;
- xfer[0].len = 1;
- xfer[0].buf = &offset;
- xfer[1].addr = adv7511->i2c_edid->addr;
- xfer[1].flags = I2C_M_RD;
- xfer[1].len = 64;
- xfer[1].buf = adv7511->edid_buf;
-
- offset = 0;
-
- for (i = 0; i < 4; ++i) {
- ret = i2c_transfer(adv7511->i2c_edid->adapter, xfer,
- ARRAY_SIZE(xfer));
- if (ret < 0)
- return ret;
- else if (ret != 2)
- return -EIO;
-
- xfer[1].buf += 64;
- offset += 64;
- }
-
- adv7511->current_edid_segment = block / 2;
- }
-
- if (block % 2 == 0)
- memcpy(buf, adv7511->edid_buf, len);
- else
- memcpy(buf, adv7511->edid_buf + 128, len);
-
- return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * Encoder operations
- */
-
-static int adv7511_get_modes(struct drm_encoder *encoder,
- struct drm_connector *connector)
-{
- struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
- struct edid *edid;
- unsigned int count;
-
- /* Reading the EDID only works if the device is powered */
- if (!adv7511->powered) {
- regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
- ADV7511_POWER_POWER_DOWN, 0);
- if (adv7511->i2c_main->irq) {
- regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
- ADV7511_INT0_EDID_READY);
- regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
- ADV7511_INT1_DDC_ERROR);
- }
- adv7511->current_edid_segment = -1;
- }
-
- edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
-
- if (!adv7511->powered)
- regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
- ADV7511_POWER_POWER_DOWN,
- ADV7511_POWER_POWER_DOWN);
-
- kfree(adv7511->edid);
- adv7511->edid = edid;
- if (!edid)
- return 0;
-
- drm_mode_connector_update_edid_property(connector, edid);
- count = drm_add_edid_modes(connector, edid);
-
- adv7511_set_config_csc(adv7511, connector, adv7511->rgb);
-
- return count;
-}
-
-static void adv7511_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
- struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
-
- if (mode == DRM_MODE_DPMS_ON)
- adv7511_power_on(adv7511);
- else
- adv7511_power_off(adv7511);
-}
-
-static enum drm_connector_status
-adv7511_encoder_detect(struct drm_encoder *encoder,
- struct drm_connector *connector)
-{
- struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
- enum drm_connector_status status;
- unsigned int val;
- bool hpd;
- int ret;
-
- ret = regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val);
- if (ret < 0)
- return connector_status_disconnected;
-
- if (val & ADV7511_STATUS_HPD)
- status = connector_status_connected;
- else
- status = connector_status_disconnected;
-
- hpd = adv7511_hpd(adv7511);
-
- /* The chip resets itself when the cable is disconnected, so in case
- * there is a pending HPD interrupt and the cable is connected there was
- * at least one transition from disconnected to connected and the chip
- * has to be reinitialized. */
- if (status == connector_status_connected && hpd && adv7511->powered) {
- regcache_mark_dirty(adv7511->regmap);
- adv7511_power_on(adv7511);
- adv7511_get_modes(encoder, connector);
- if (adv7511->status == connector_status_connected)
- status = connector_status_disconnected;
- } else {
- /* Renable HPD sensing */
- regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
- ADV7511_REG_POWER2_HPD_SRC_MASK,
- ADV7511_REG_POWER2_HPD_SRC_BOTH);
- }
-
- adv7511->status = status;
- return status;
-}
-
-static int adv7511_encoder_mode_valid(struct drm_encoder *encoder,
- struct drm_display_mode *mode)
-{
- if (mode->clock > 165000)
- return MODE_CLOCK_HIGH;
-
- return MODE_OK;
-}
-
-static void adv7511_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adj_mode)
-{
- struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
- unsigned int low_refresh_rate;
- unsigned int hsync_polarity = 0;
- unsigned int vsync_polarity = 0;
-
- if (adv7511->embedded_sync) {
- unsigned int hsync_offset, hsync_len;
- unsigned int vsync_offset, vsync_len;
-
- hsync_offset = adj_mode->crtc_hsync_start -
- adj_mode->crtc_hdisplay;
- vsync_offset = adj_mode->crtc_vsync_start -
- adj_mode->crtc_vdisplay;
- hsync_len = adj_mode->crtc_hsync_end -
- adj_mode->crtc_hsync_start;
- vsync_len = adj_mode->crtc_vsync_end -
- adj_mode->crtc_vsync_start;
-
- /* The hardware vsync generator has a off-by-one bug */
- vsync_offset += 1;
-
- regmap_write(adv7511->regmap, ADV7511_REG_HSYNC_PLACEMENT_MSB,
- ((hsync_offset >> 10) & 0x7) << 5);
- regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(0),
- (hsync_offset >> 2) & 0xff);
- regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(1),
- ((hsync_offset & 0x3) << 6) |
- ((hsync_len >> 4) & 0x3f));
- regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(2),
- ((hsync_len & 0xf) << 4) |
- ((vsync_offset >> 6) & 0xf));
- regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(3),
- ((vsync_offset & 0x3f) << 2) |
- ((vsync_len >> 8) & 0x3));
- regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(4),
- vsync_len & 0xff);
-
- hsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PHSYNC);
- vsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PVSYNC);
- } else {
- enum adv7511_sync_polarity mode_hsync_polarity;
- enum adv7511_sync_polarity mode_vsync_polarity;
-
- /**
- * If the input signal is always low or always high we want to
- * invert or let it passthrough depending on the polarity of the
- * current mode.
- **/
- if (adj_mode->flags & DRM_MODE_FLAG_NHSYNC)
- mode_hsync_polarity = ADV7511_SYNC_POLARITY_LOW;
- else
- mode_hsync_polarity = ADV7511_SYNC_POLARITY_HIGH;
-
- if (adj_mode->flags & DRM_MODE_FLAG_NVSYNC)
- mode_vsync_polarity = ADV7511_SYNC_POLARITY_LOW;
- else
- mode_vsync_polarity = ADV7511_SYNC_POLARITY_HIGH;
-
- if (adv7511->hsync_polarity != mode_hsync_polarity &&
- adv7511->hsync_polarity !=
- ADV7511_SYNC_POLARITY_PASSTHROUGH)
- hsync_polarity = 1;
-
- if (adv7511->vsync_polarity != mode_vsync_polarity &&
- adv7511->vsync_polarity !=
- ADV7511_SYNC_POLARITY_PASSTHROUGH)
- vsync_polarity = 1;
- }
-
- if (mode->vrefresh <= 24000)
- low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ;
- else if (mode->vrefresh <= 25000)
- low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ;
- else if (mode->vrefresh <= 30000)
- low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ;
- else
- low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE;
-
- regmap_update_bits(adv7511->regmap, 0xfb,
- 0x6, low_refresh_rate << 1);
- regmap_update_bits(adv7511->regmap, 0x17,
- 0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
-
- /*
- * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is
- * supposed to give better results.
- */
-
- adv7511->f_tmds = mode->clock;
-}
-
-static const struct drm_encoder_slave_funcs adv7511_encoder_funcs = {
- .dpms = adv7511_encoder_dpms,
- .mode_valid = adv7511_encoder_mode_valid,
- .mode_set = adv7511_encoder_mode_set,
- .detect = adv7511_encoder_detect,
- .get_modes = adv7511_get_modes,
-};
-
-/* -----------------------------------------------------------------------------
- * Probe & remove
- */
-
-static int adv7511_parse_dt(struct device_node *np,
- struct adv7511_link_config *config)
-{
- const char *str;
- int ret;
-
- memset(config, 0, sizeof(*config));
-
- of_property_read_u32(np, "adi,input-depth", &config->input_color_depth);
- if (config->input_color_depth != 8 && config->input_color_depth != 10 &&
- config->input_color_depth != 12)
- return -EINVAL;
-
- ret = of_property_read_string(np, "adi,input-colorspace", &str);
- if (ret < 0)
- return ret;
-
- if (!strcmp(str, "rgb"))
- config->input_colorspace = HDMI_COLORSPACE_RGB;
- else if (!strcmp(str, "yuv422"))
- config->input_colorspace = HDMI_COLORSPACE_YUV422;
- else if (!strcmp(str, "yuv444"))
- config->input_colorspace = HDMI_COLORSPACE_YUV444;
- else
- return -EINVAL;
-
- ret = of_property_read_string(np, "adi,input-clock", &str);
- if (ret < 0)
- return ret;
-
- if (!strcmp(str, "1x"))
- config->input_clock = ADV7511_INPUT_CLOCK_1X;
- else if (!strcmp(str, "2x"))
- config->input_clock = ADV7511_INPUT_CLOCK_2X;
- else if (!strcmp(str, "ddr"))
- config->input_clock = ADV7511_INPUT_CLOCK_DDR;
- else
- return -EINVAL;
-
- if (config->input_colorspace == HDMI_COLORSPACE_YUV422 ||
- config->input_clock != ADV7511_INPUT_CLOCK_1X) {
- ret = of_property_read_u32(np, "adi,input-style",
- &config->input_style);
- if (ret)
- return ret;
-
- if (config->input_style < 1 || config->input_style > 3)
- return -EINVAL;
-
- ret = of_property_read_string(np, "adi,input-justification",
- &str);
- if (ret < 0)
- return ret;
-
- if (!strcmp(str, "left"))
- config->input_justification =
- ADV7511_INPUT_JUSTIFICATION_LEFT;
- else if (!strcmp(str, "evenly"))
- config->input_justification =
- ADV7511_INPUT_JUSTIFICATION_EVENLY;
- else if (!strcmp(str, "right"))
- config->input_justification =
- ADV7511_INPUT_JUSTIFICATION_RIGHT;
- else
- return -EINVAL;
-
- } else {
- config->input_style = 1;
- config->input_justification = ADV7511_INPUT_JUSTIFICATION_LEFT;
- }
-
- of_property_read_u32(np, "adi,clock-delay", &config->clock_delay);
- if (config->clock_delay < -1200 || config->clock_delay > 1600)
- return -EINVAL;
-
- config->embedded_sync = of_property_read_bool(np, "adi,embedded-sync");
-
- /* Hardcode the sync pulse configurations for now. */
- config->sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE;
- config->vsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH;
- config->hsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH;
-
- return 0;
-}
-
-static const int edid_i2c_addr = 0x7e;
-static const int packet_i2c_addr = 0x70;
-static const int cec_i2c_addr = 0x78;
-
-static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
-{
- struct adv7511_link_config link_config;
- struct adv7511 *adv7511;
- struct device *dev = &i2c->dev;
- unsigned int val;
- int ret;
-
- if (!dev->of_node)
- return -EINVAL;
-
- adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
- if (!adv7511)
- return -ENOMEM;
-
- adv7511->powered = false;
- adv7511->status = connector_status_disconnected;
-
- ret = adv7511_parse_dt(dev->of_node, &link_config);
- if (ret)
- return ret;
-
- /*
- * The power down GPIO is optional. If present, toggle it from active to
- * inactive to wake up the encoder.
- */
- adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
- if (IS_ERR(adv7511->gpio_pd))
- return PTR_ERR(adv7511->gpio_pd);
-
- if (adv7511->gpio_pd) {
- mdelay(5);
- gpiod_set_value_cansleep(adv7511->gpio_pd, 0);
- }
-
- adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config);
- if (IS_ERR(adv7511->regmap))
- return PTR_ERR(adv7511->regmap);
-
- ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val);
- if (ret)
- return ret;
- dev_dbg(dev, "Rev. %d\n", val);
-
- ret = regmap_register_patch(adv7511->regmap, adv7511_fixed_registers,
- ARRAY_SIZE(adv7511_fixed_registers));
- if (ret)
- return ret;
-
- regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr);
- regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
- packet_i2c_addr);
- regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr);
- adv7511_packet_disable(adv7511, 0xffff);
-
- adv7511->i2c_main = i2c;
- adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
- if (!adv7511->i2c_edid)
- return -ENOMEM;
-
- if (i2c->irq) {
- init_waitqueue_head(&adv7511->wq);
-
- ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
- adv7511_irq_handler,
- IRQF_ONESHOT, dev_name(dev),
- adv7511);
- if (ret)
- goto err_i2c_unregister_device;
- }
-
- /* CEC is unused for now */
- regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
- ADV7511_CEC_CTRL_POWER_DOWN);
-
- adv7511_power_off(adv7511);
-
- i2c_set_clientdata(i2c, adv7511);
-
- adv7511_set_link_config(adv7511, &link_config);
-
- return 0;
-
-err_i2c_unregister_device:
- i2c_unregister_device(adv7511->i2c_edid);
-
- return ret;
-}
-
-static int adv7511_remove(struct i2c_client *i2c)
-{
- struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
-
- i2c_unregister_device(adv7511->i2c_edid);
-
- kfree(adv7511->edid);
-
- return 0;
-}
-
-static int adv7511_encoder_init(struct i2c_client *i2c, struct drm_device *dev,
- struct drm_encoder_slave *encoder)
-{
-
- struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
-
- encoder->slave_priv = adv7511;
- encoder->slave_funcs = &adv7511_encoder_funcs;
-
- adv7511->encoder = &encoder->base;
-
- return 0;
-}
-
-static const struct i2c_device_id adv7511_i2c_ids[] = {
- { "adv7511", 0 },
- { "adv7511w", 0 },
- { "adv7513", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adv7511_i2c_ids);
-
-static const struct of_device_id adv7511_of_ids[] = {
- { .compatible = "adi,adv7511", },
- { .compatible = "adi,adv7511w", },
- { .compatible = "adi,adv7513", },
- { }
-};
-MODULE_DEVICE_TABLE(of, adv7511_of_ids);
-
-static struct drm_i2c_encoder_driver adv7511_driver = {
- .i2c_driver = {
- .driver = {
- .name = "adv7511",
- .of_match_table = adv7511_of_ids,
- },
- .id_table = adv7511_i2c_ids,
- .probe = adv7511_probe,
- .remove = adv7511_remove,
- },
-
- .encoder_init = adv7511_encoder_init,
-};
-
-static int __init adv7511_init(void)
-{
- return drm_i2c_encoder_register(THIS_MODULE, &adv7511_driver);
-}
-module_init(adv7511_init);
-
-static void __exit adv7511_exit(void)
-{
- drm_i2c_encoder_unregister(&adv7511_driver);
-}
-module_exit(adv7511_exit);
-
-MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
-MODULE_DESCRIPTION("ADV7511 HDMI transmitter driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/i2c/adv7511.h b/drivers/gpu/drm/i2c/adv7511.h
deleted file mode 100644
index 38515b30c..000000000
--- a/drivers/gpu/drm/i2c/adv7511.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Analog Devices ADV7511 HDMI transmitter driver
- *
- * Copyright 2012 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#ifndef __DRM_I2C_ADV7511_H__
-#define __DRM_I2C_ADV7511_H__
-
-#include <linux/hdmi.h>
-
-#define ADV7511_REG_CHIP_REVISION 0x00
-#define ADV7511_REG_N0 0x01
-#define ADV7511_REG_N1 0x02
-#define ADV7511_REG_N2 0x03
-#define ADV7511_REG_SPDIF_FREQ 0x04
-#define ADV7511_REG_CTS_AUTOMATIC1 0x05
-#define ADV7511_REG_CTS_AUTOMATIC2 0x06
-#define ADV7511_REG_CTS_MANUAL0 0x07
-#define ADV7511_REG_CTS_MANUAL1 0x08
-#define ADV7511_REG_CTS_MANUAL2 0x09
-#define ADV7511_REG_AUDIO_SOURCE 0x0a
-#define ADV7511_REG_AUDIO_CONFIG 0x0b
-#define ADV7511_REG_I2S_CONFIG 0x0c
-#define ADV7511_REG_I2S_WIDTH 0x0d
-#define ADV7511_REG_AUDIO_SUB_SRC0 0x0e
-#define ADV7511_REG_AUDIO_SUB_SRC1 0x0f
-#define ADV7511_REG_AUDIO_SUB_SRC2 0x10
-#define ADV7511_REG_AUDIO_SUB_SRC3 0x11
-#define ADV7511_REG_AUDIO_CFG1 0x12
-#define ADV7511_REG_AUDIO_CFG2 0x13
-#define ADV7511_REG_AUDIO_CFG3 0x14
-#define ADV7511_REG_I2C_FREQ_ID_CFG 0x15
-#define ADV7511_REG_VIDEO_INPUT_CFG1 0x16
-#define ADV7511_REG_CSC_UPPER(x) (0x18 + (x) * 2)
-#define ADV7511_REG_CSC_LOWER(x) (0x19 + (x) * 2)
-#define ADV7511_REG_SYNC_DECODER(x) (0x30 + (x))
-#define ADV7511_REG_DE_GENERATOR (0x35 + (x))
-#define ADV7511_REG_PIXEL_REPETITION 0x3b
-#define ADV7511_REG_VIC_MANUAL 0x3c
-#define ADV7511_REG_VIC_SEND 0x3d
-#define ADV7511_REG_VIC_DETECTED 0x3e
-#define ADV7511_REG_AUX_VIC_DETECTED 0x3f
-#define ADV7511_REG_PACKET_ENABLE0 0x40
-#define ADV7511_REG_POWER 0x41
-#define ADV7511_REG_STATUS 0x42
-#define ADV7511_REG_EDID_I2C_ADDR 0x43
-#define ADV7511_REG_PACKET_ENABLE1 0x44
-#define ADV7511_REG_PACKET_I2C_ADDR 0x45
-#define ADV7511_REG_DSD_ENABLE 0x46
-#define ADV7511_REG_VIDEO_INPUT_CFG2 0x48
-#define ADV7511_REG_INFOFRAME_UPDATE 0x4a
-#define ADV7511_REG_GC(x) (0x4b + (x)) /* 0x4b - 0x51 */
-#define ADV7511_REG_AVI_INFOFRAME_VERSION 0x52
-#define ADV7511_REG_AVI_INFOFRAME_LENGTH 0x53
-#define ADV7511_REG_AVI_INFOFRAME_CHECKSUM 0x54
-#define ADV7511_REG_AVI_INFOFRAME(x) (0x55 + (x)) /* 0x55 - 0x6f */
-#define ADV7511_REG_AUDIO_INFOFRAME_VERSION 0x70
-#define ADV7511_REG_AUDIO_INFOFRAME_LENGTH 0x71
-#define ADV7511_REG_AUDIO_INFOFRAME_CHECKSUM 0x72
-#define ADV7511_REG_AUDIO_INFOFRAME(x) (0x73 + (x)) /* 0x73 - 0x7c */
-#define ADV7511_REG_INT_ENABLE(x) (0x94 + (x))
-#define ADV7511_REG_INT(x) (0x96 + (x))
-#define ADV7511_REG_INPUT_CLK_DIV 0x9d
-#define ADV7511_REG_PLL_STATUS 0x9e
-#define ADV7511_REG_HDMI_POWER 0xa1
-#define ADV7511_REG_HDCP_HDMI_CFG 0xaf
-#define ADV7511_REG_AN(x) (0xb0 + (x)) /* 0xb0 - 0xb7 */
-#define ADV7511_REG_HDCP_STATUS 0xb8
-#define ADV7511_REG_BCAPS 0xbe
-#define ADV7511_REG_BKSV(x) (0xc0 + (x)) /* 0xc0 - 0xc3 */
-#define ADV7511_REG_EDID_SEGMENT 0xc4
-#define ADV7511_REG_DDC_STATUS 0xc8
-#define ADV7511_REG_EDID_READ_CTRL 0xc9
-#define ADV7511_REG_BSTATUS(x) (0xca + (x)) /* 0xca - 0xcb */
-#define ADV7511_REG_TIMING_GEN_SEQ 0xd0
-#define ADV7511_REG_POWER2 0xd6
-#define ADV7511_REG_HSYNC_PLACEMENT_MSB 0xfa
-
-#define ADV7511_REG_SYNC_ADJUSTMENT(x) (0xd7 + (x)) /* 0xd7 - 0xdc */
-#define ADV7511_REG_TMDS_CLOCK_INV 0xde
-#define ADV7511_REG_ARC_CTRL 0xdf
-#define ADV7511_REG_CEC_I2C_ADDR 0xe1
-#define ADV7511_REG_CEC_CTRL 0xe2
-#define ADV7511_REG_CHIP_ID_HIGH 0xf5
-#define ADV7511_REG_CHIP_ID_LOW 0xf6
-
-#define ADV7511_CSC_ENABLE BIT(7)
-#define ADV7511_CSC_UPDATE_MODE BIT(5)
-
-#define ADV7511_INT0_HPD BIT(7)
-#define ADV7511_INT0_VSYNC BIT(5)
-#define ADV7511_INT0_AUDIO_FIFO_FULL BIT(4)
-#define ADV7511_INT0_EDID_READY BIT(2)
-#define ADV7511_INT0_HDCP_AUTHENTICATED BIT(1)
-
-#define ADV7511_INT1_DDC_ERROR BIT(7)
-#define ADV7511_INT1_BKSV BIT(6)
-#define ADV7511_INT1_CEC_TX_READY BIT(5)
-#define ADV7511_INT1_CEC_TX_ARBIT_LOST BIT(4)
-#define ADV7511_INT1_CEC_TX_RETRY_TIMEOUT BIT(3)
-#define ADV7511_INT1_CEC_RX_READY3 BIT(2)
-#define ADV7511_INT1_CEC_RX_READY2 BIT(1)
-#define ADV7511_INT1_CEC_RX_READY1 BIT(0)
-
-#define ADV7511_ARC_CTRL_POWER_DOWN BIT(0)
-
-#define ADV7511_CEC_CTRL_POWER_DOWN BIT(0)
-
-#define ADV7511_POWER_POWER_DOWN BIT(6)
-
-#define ADV7511_HDMI_CFG_MODE_MASK 0x2
-#define ADV7511_HDMI_CFG_MODE_DVI 0x0
-#define ADV7511_HDMI_CFG_MODE_HDMI 0x2
-
-#define ADV7511_AUDIO_SELECT_I2C 0x0
-#define ADV7511_AUDIO_SELECT_SPDIF 0x1
-#define ADV7511_AUDIO_SELECT_DSD 0x2
-#define ADV7511_AUDIO_SELECT_HBR 0x3
-#define ADV7511_AUDIO_SELECT_DST 0x4
-
-#define ADV7511_I2S_SAMPLE_LEN_16 0x2
-#define ADV7511_I2S_SAMPLE_LEN_20 0x3
-#define ADV7511_I2S_SAMPLE_LEN_18 0x4
-#define ADV7511_I2S_SAMPLE_LEN_22 0x5
-#define ADV7511_I2S_SAMPLE_LEN_19 0x8
-#define ADV7511_I2S_SAMPLE_LEN_23 0x9
-#define ADV7511_I2S_SAMPLE_LEN_24 0xb
-#define ADV7511_I2S_SAMPLE_LEN_17 0xc
-#define ADV7511_I2S_SAMPLE_LEN_21 0xd
-
-#define ADV7511_SAMPLE_FREQ_44100 0x0
-#define ADV7511_SAMPLE_FREQ_48000 0x2
-#define ADV7511_SAMPLE_FREQ_32000 0x3
-#define ADV7511_SAMPLE_FREQ_88200 0x8
-#define ADV7511_SAMPLE_FREQ_96000 0xa
-#define ADV7511_SAMPLE_FREQ_176400 0xc
-#define ADV7511_SAMPLE_FREQ_192000 0xe
-
-#define ADV7511_STATUS_POWER_DOWN_POLARITY BIT(7)
-#define ADV7511_STATUS_HPD BIT(6)
-#define ADV7511_STATUS_MONITOR_SENSE BIT(5)
-#define ADV7511_STATUS_I2S_32BIT_MODE BIT(3)
-
-#define ADV7511_PACKET_ENABLE_N_CTS BIT(8+6)
-#define ADV7511_PACKET_ENABLE_AUDIO_SAMPLE BIT(8+5)
-#define ADV7511_PACKET_ENABLE_AVI_INFOFRAME BIT(8+4)
-#define ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME BIT(8+3)
-#define ADV7511_PACKET_ENABLE_GC BIT(7)
-#define ADV7511_PACKET_ENABLE_SPD BIT(6)
-#define ADV7511_PACKET_ENABLE_MPEG BIT(5)
-#define ADV7511_PACKET_ENABLE_ACP BIT(4)
-#define ADV7511_PACKET_ENABLE_ISRC BIT(3)
-#define ADV7511_PACKET_ENABLE_GM BIT(2)
-#define ADV7511_PACKET_ENABLE_SPARE2 BIT(1)
-#define ADV7511_PACKET_ENABLE_SPARE1 BIT(0)
-
-#define ADV7511_REG_POWER2_HPD_SRC_MASK 0xc0
-#define ADV7511_REG_POWER2_HPD_SRC_BOTH 0x00
-#define ADV7511_REG_POWER2_HPD_SRC_HPD 0x40
-#define ADV7511_REG_POWER2_HPD_SRC_CEC 0x80
-#define ADV7511_REG_POWER2_HPD_SRC_NONE 0xc0
-#define ADV7511_REG_POWER2_TDMS_ENABLE BIT(4)
-#define ADV7511_REG_POWER2_GATE_INPUT_CLK BIT(0)
-
-#define ADV7511_LOW_REFRESH_RATE_NONE 0x0
-#define ADV7511_LOW_REFRESH_RATE_24HZ 0x1
-#define ADV7511_LOW_REFRESH_RATE_25HZ 0x2
-#define ADV7511_LOW_REFRESH_RATE_30HZ 0x3
-
-#define ADV7511_AUDIO_CFG3_LEN_MASK 0x0f
-#define ADV7511_I2C_FREQ_ID_CFG_RATE_MASK 0xf0
-
-#define ADV7511_AUDIO_SOURCE_I2S 0
-#define ADV7511_AUDIO_SOURCE_SPDIF 1
-
-#define ADV7511_I2S_FORMAT_I2S 0
-#define ADV7511_I2S_FORMAT_RIGHT_J 1
-#define ADV7511_I2S_FORMAT_LEFT_J 2
-
-#define ADV7511_PACKET(p, x) ((p) * 0x20 + (x))
-#define ADV7511_PACKET_SDP(x) ADV7511_PACKET(0, x)
-#define ADV7511_PACKET_MPEG(x) ADV7511_PACKET(1, x)
-#define ADV7511_PACKET_ACP(x) ADV7511_PACKET(2, x)
-#define ADV7511_PACKET_ISRC1(x) ADV7511_PACKET(3, x)
-#define ADV7511_PACKET_ISRC2(x) ADV7511_PACKET(4, x)
-#define ADV7511_PACKET_GM(x) ADV7511_PACKET(5, x)
-#define ADV7511_PACKET_SPARE(x) ADV7511_PACKET(6, x)
-
-enum adv7511_input_clock {
- ADV7511_INPUT_CLOCK_1X,
- ADV7511_INPUT_CLOCK_2X,
- ADV7511_INPUT_CLOCK_DDR,
-};
-
-enum adv7511_input_justification {
- ADV7511_INPUT_JUSTIFICATION_EVENLY = 0,
- ADV7511_INPUT_JUSTIFICATION_RIGHT = 1,
- ADV7511_INPUT_JUSTIFICATION_LEFT = 2,
-};
-
-enum adv7511_input_sync_pulse {
- ADV7511_INPUT_SYNC_PULSE_DE = 0,
- ADV7511_INPUT_SYNC_PULSE_HSYNC = 1,
- ADV7511_INPUT_SYNC_PULSE_VSYNC = 2,
- ADV7511_INPUT_SYNC_PULSE_NONE = 3,
-};
-
-/**
- * enum adv7511_sync_polarity - Polarity for the input sync signals
- * @ADV7511_SYNC_POLARITY_PASSTHROUGH: Sync polarity matches that of
- * the currently configured mode.
- * @ADV7511_SYNC_POLARITY_LOW: Sync polarity is low
- * @ADV7511_SYNC_POLARITY_HIGH: Sync polarity is high
- *
- * If the polarity is set to either LOW or HIGH the driver will configure the
- * ADV7511 to internally invert the sync signal if required to match the sync
- * polarity setting for the currently selected output mode.
- *
- * If the polarity is set to PASSTHROUGH, the ADV7511 will route the signal
- * unchanged. This is used when the upstream graphics core already generates
- * the sync signals with the correct polarity.
- */
-enum adv7511_sync_polarity {
- ADV7511_SYNC_POLARITY_PASSTHROUGH,
- ADV7511_SYNC_POLARITY_LOW,
- ADV7511_SYNC_POLARITY_HIGH,
-};
-
-/**
- * struct adv7511_link_config - Describes adv7511 hardware configuration
- * @input_color_depth: Number of bits per color component (8, 10 or 12)
- * @input_colorspace: The input colorspace (RGB, YUV444, YUV422)
- * @input_clock: The input video clock style (1x, 2x, DDR)
- * @input_style: The input component arrangement variant
- * @input_justification: Video input format bit justification
- * @clock_delay: Clock delay for the input clock (in ps)
- * @embedded_sync: Video input uses BT.656-style embedded sync
- * @sync_pulse: Select the sync pulse
- * @vsync_polarity: vsync input signal configuration
- * @hsync_polarity: hsync input signal configuration
- */
-struct adv7511_link_config {
- unsigned int input_color_depth;
- enum hdmi_colorspace input_colorspace;
- enum adv7511_input_clock input_clock;
- unsigned int input_style;
- enum adv7511_input_justification input_justification;
-
- int clock_delay;
-
- bool embedded_sync;
- enum adv7511_input_sync_pulse sync_pulse;
- enum adv7511_sync_polarity vsync_polarity;
- enum adv7511_sync_polarity hsync_polarity;
-};
-
-/**
- * enum adv7511_csc_scaling - Scaling factor for the ADV7511 CSC
- * @ADV7511_CSC_SCALING_1: CSC results are not scaled
- * @ADV7511_CSC_SCALING_2: CSC results are scaled by a factor of two
- * @ADV7511_CSC_SCALING_4: CSC results are scalled by a factor of four
- */
-enum adv7511_csc_scaling {
- ADV7511_CSC_SCALING_1 = 0,
- ADV7511_CSC_SCALING_2 = 1,
- ADV7511_CSC_SCALING_4 = 2,
-};
-
-/**
- * struct adv7511_video_config - Describes adv7511 hardware configuration
- * @csc_enable: Whether to enable color space conversion
- * @csc_scaling_factor: Color space conversion scaling factor
- * @csc_coefficents: Color space conversion coefficents
- * @hdmi_mode: Whether to use HDMI or DVI output mode
- * @avi_infoframe: HDMI infoframe
- */
-struct adv7511_video_config {
- bool csc_enable;
- enum adv7511_csc_scaling csc_scaling_factor;
- const uint16_t *csc_coefficents;
-
- bool hdmi_mode;
- struct hdmi_avi_infoframe avi_infoframe;
-};
-
-#endif /* __DRM_I2C_ADV7511_H__ */
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
deleted file mode 100644
index b3198fcd0..000000000
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ /dev/null
@@ -1,1587 +0,0 @@
-/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
- */
-/*
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_legacy.h>
-#include "intel_drv.h"
-#include <drm/i915_drm.h>
-#include "i915_drv.h"
-#include "i915_vgpu.h"
-#include "i915_trace.h"
-#include <linux/pci.h>
-#include <linux/console.h>
-#include <linux/vt.h>
-#include <linux/vgaarb.h>
-#include <linux/acpi.h>
-#include <linux/pnp.h>
-#include <linux/vga_switcheroo.h>
-#include <linux/slab.h>
-#include <acpi/video.h>
-#include <linux/pm.h>
-#include <linux/pm_runtime.h>
-#include <linux/oom.h>
-
-static unsigned int i915_load_fail_count;
-
-bool __i915_inject_load_failure(const char *func, int line)
-{
- if (i915_load_fail_count >= i915.inject_load_failure)
- return false;
-
- if (++i915_load_fail_count == i915.inject_load_failure) {
- DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n",
- i915.inject_load_failure, func, line);
- return true;
- }
-
- return false;
-}
-
-#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI"
-#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \
- "providing the dmesg log by booting with drm.debug=0xf"
-
-void
-__i915_printk(struct drm_i915_private *dev_priv, const char *level,
- const char *fmt, ...)
-{
- static bool shown_bug_once;
- struct device *dev = dev_priv->dev->dev;
- bool is_error = level[1] <= KERN_ERR[1];
- bool is_debug = level[1] == KERN_DEBUG[1];
- struct va_format vaf;
- va_list args;
-
- if (is_debug && !(drm_debug & DRM_UT_DRIVER))
- return;
-
- va_start(args, fmt);
-
- vaf.fmt = fmt;
- vaf.va = &args;
-
- dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
- __builtin_return_address(0), &vaf);
-
- if (is_error && !shown_bug_once) {
- dev_notice(dev, "%s", FDO_BUG_MSG);
- shown_bug_once = true;
- }
-
- va_end(args);
-}
-
-static bool i915_error_injected(struct drm_i915_private *dev_priv)
-{
- return i915.inject_load_failure &&
- i915_load_fail_count == i915.inject_load_failure;
-}
-
-#define i915_load_error(dev_priv, fmt, ...) \
- __i915_printk(dev_priv, \
- i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \
- fmt, ##__VA_ARGS__)
-
-static int i915_getparam(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- drm_i915_getparam_t *param = data;
- int value;
-
- switch (param->param) {
- case I915_PARAM_IRQ_ACTIVE:
- case I915_PARAM_ALLOW_BATCHBUFFER:
- case I915_PARAM_LAST_DISPATCH:
- /* Reject all old ums/dri params. */
- return -ENODEV;
- case I915_PARAM_CHIPSET_ID:
- value = dev->pdev->device;
- break;
- case I915_PARAM_REVISION:
- value = dev->pdev->revision;
- break;
- case I915_PARAM_HAS_GEM:
- value = 1;
- break;
- case I915_PARAM_NUM_FENCES_AVAIL:
- value = dev_priv->num_fence_regs;
- break;
- case I915_PARAM_HAS_OVERLAY:
- value = dev_priv->overlay ? 1 : 0;
- break;
- case I915_PARAM_HAS_PAGEFLIPPING:
- value = 1;
- break;
- case I915_PARAM_HAS_EXECBUF2:
- /* depends on GEM */
- value = 1;
- break;
- case I915_PARAM_HAS_BSD:
- value = intel_engine_initialized(&dev_priv->engine[VCS]);
- break;
- case I915_PARAM_HAS_BLT:
- value = intel_engine_initialized(&dev_priv->engine[BCS]);
- break;
- case I915_PARAM_HAS_VEBOX:
- value = intel_engine_initialized(&dev_priv->engine[VECS]);
- break;
- case I915_PARAM_HAS_BSD2:
- value = intel_engine_initialized(&dev_priv->engine[VCS2]);
- break;
- case I915_PARAM_HAS_RELAXED_FENCING:
- value = 1;
- break;
- case I915_PARAM_HAS_COHERENT_RINGS:
- value = 1;
- break;
- case I915_PARAM_HAS_EXEC_CONSTANTS:
- value = INTEL_INFO(dev)->gen >= 4;
- break;
- case I915_PARAM_HAS_RELAXED_DELTA:
- value = 1;
- break;
- case I915_PARAM_HAS_GEN7_SOL_RESET:
- value = 1;
- break;
- case I915_PARAM_HAS_LLC:
- value = HAS_LLC(dev);
- break;
- case I915_PARAM_HAS_WT:
- value = HAS_WT(dev);
- break;
- case I915_PARAM_HAS_ALIASING_PPGTT:
- value = USES_PPGTT(dev);
- break;
- case I915_PARAM_HAS_WAIT_TIMEOUT:
- value = 1;
- break;
- case I915_PARAM_HAS_SEMAPHORES:
- value = i915_semaphore_is_enabled(dev);
- break;
- case I915_PARAM_HAS_PRIME_VMAP_FLUSH:
- value = 1;
- break;
- case I915_PARAM_HAS_SECURE_BATCHES:
- value = capable(CAP_SYS_ADMIN);
- break;
- case I915_PARAM_HAS_PINNED_BATCHES:
- value = 1;
- break;
- case I915_PARAM_HAS_EXEC_NO_RELOC:
- value = 1;
- break;
- case I915_PARAM_HAS_EXEC_HANDLE_LUT:
- value = 1;
- break;
- case I915_PARAM_CMD_PARSER_VERSION:
- value = i915_cmd_parser_get_version();
- break;
- case I915_PARAM_HAS_COHERENT_PHYS_GTT:
- value = 1;
- break;
- case I915_PARAM_MMAP_VERSION:
- value = 1;
- break;
- case I915_PARAM_SUBSLICE_TOTAL:
- value = INTEL_INFO(dev)->subslice_total;
- if (!value)
- return -ENODEV;
- break;
- case I915_PARAM_EU_TOTAL:
- value = INTEL_INFO(dev)->eu_total;
- if (!value)
- return -ENODEV;
- break;
- case I915_PARAM_HAS_GPU_RESET:
- value = i915.enable_hangcheck &&
- intel_has_gpu_reset(dev);
- break;
- case I915_PARAM_HAS_RESOURCE_STREAMER:
- value = HAS_RESOURCE_STREAMER(dev);
- break;
- case I915_PARAM_HAS_EXEC_SOFTPIN:
- value = 1;
- break;
- default:
- DRM_DEBUG("Unknown parameter %d\n", param->param);
- return -EINVAL;
- }
-
- if (copy_to_user(param->value, &value, sizeof(int))) {
- DRM_ERROR("copy_to_user failed\n");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int i915_get_bridge_dev(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
- if (!dev_priv->bridge_dev) {
- DRM_ERROR("bridge device not found\n");
- return -1;
- }
- return 0;
-}
-
-/* Allocate space for the MCH regs if needed, return nonzero on error */
-static int
-intel_alloc_mchbar_resource(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
- u32 temp_lo, temp_hi = 0;
- u64 mchbar_addr;
- int ret;
-
- if (INTEL_INFO(dev)->gen >= 4)
- pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
- pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
- mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
-
- /* If ACPI doesn't have it, assume we need to allocate it ourselves */
-#ifdef CONFIG_PNP
- if (mchbar_addr &&
- pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE))
- return 0;
-#endif
-
- /* Get some space for it */
- dev_priv->mch_res.name = "i915 MCHBAR";
- dev_priv->mch_res.flags = IORESOURCE_MEM;
- ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus,
- &dev_priv->mch_res,
- MCHBAR_SIZE, MCHBAR_SIZE,
- PCIBIOS_MIN_MEM,
- 0, pcibios_align_resource,
- dev_priv->bridge_dev);
- if (ret) {
- DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
- dev_priv->mch_res.start = 0;
- return ret;
- }
-
- if (INTEL_INFO(dev)->gen >= 4)
- pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
- upper_32_bits(dev_priv->mch_res.start));
-
- pci_write_config_dword(dev_priv->bridge_dev, reg,
- lower_32_bits(dev_priv->mch_res.start));
- return 0;
-}
-
-/* Setup MCHBAR if possible, return true if we should disable it again */
-static void
-intel_setup_mchbar(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
- u32 temp;
- bool enabled;
-
- if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
- return;
-
- dev_priv->mchbar_need_disable = false;
-
- if (IS_I915G(dev) || IS_I915GM(dev)) {
- pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp);
- enabled = !!(temp & DEVEN_MCHBAR_EN);
- } else {
- pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
- enabled = temp & 1;
- }
-
- /* If it's already enabled, don't have to do anything */
- if (enabled)
- return;
-
- if (intel_alloc_mchbar_resource(dev))
- return;
-
- dev_priv->mchbar_need_disable = true;
-
- /* Space is allocated or reserved, so enable it. */
- if (IS_I915G(dev) || IS_I915GM(dev)) {
- pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
- temp | DEVEN_MCHBAR_EN);
- } else {
- pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
- pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
- }
-}
-
-static void
-intel_teardown_mchbar(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
-
- if (dev_priv->mchbar_need_disable) {
- if (IS_I915G(dev) || IS_I915GM(dev)) {
- u32 deven_val;
-
- pci_read_config_dword(dev_priv->bridge_dev, DEVEN,
- &deven_val);
- deven_val &= ~DEVEN_MCHBAR_EN;
- pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
- deven_val);
- } else {
- u32 mchbar_val;
-
- pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg,
- &mchbar_val);
- mchbar_val &= ~1;
- pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg,
- mchbar_val);
- }
- }
-
- if (dev_priv->mch_res.start)
- release_resource(&dev_priv->mch_res);
-}
-
-/* true = enable decode, false = disable decoder */
-static unsigned int i915_vga_set_decode(void *cookie, bool state)
-{
- struct drm_device *dev = cookie;
-
- intel_modeset_vga_set_state(dev, state);
- if (state)
- return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
- VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
- else
- return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
-}
-
-static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
- pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
-
- if (state == VGA_SWITCHEROO_ON) {
- pr_info("switched on\n");
- dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- /* i915 resume handler doesn't set to D0 */
- pci_set_power_state(dev->pdev, PCI_D0);
- i915_resume_switcheroo(dev);
- dev->switch_power_state = DRM_SWITCH_POWER_ON;
- } else {
- pr_info("switched off\n");
- dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- i915_suspend_switcheroo(dev, pmm);
- dev->switch_power_state = DRM_SWITCH_POWER_OFF;
- }
-}
-
-static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
-
- /*
- * FIXME: open_count is protected by drm_global_mutex but that would lead to
- * locking inversion with the driver load path. And the access here is
- * completely racy anyway. So don't bother with locking for now.
- */
- return dev->open_count == 0;
-}
-
-static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
- .set_gpu_state = i915_switcheroo_set_state,
- .reprobe = NULL,
- .can_switch = i915_switcheroo_can_switch,
-};
-
-static int i915_load_modeset_init(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int ret;
-
- if (i915_inject_load_failure())
- return -ENODEV;
-
- ret = intel_bios_init(dev_priv);
- if (ret)
- DRM_INFO("failed to find VBIOS tables\n");
-
- /* If we have > 1 VGA cards, then we need to arbitrate access
- * to the common VGA resources.
- *
- * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA),
- * then we do not take part in VGA arbitration and the
- * vga_client_register() fails with -ENODEV.
- */
- ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
- if (ret && ret != -ENODEV)
- goto out;
-
- intel_register_dsm_handler();
-
- ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops, false);
- if (ret)
- goto cleanup_vga_client;
-
- intel_power_domains_init_hw(dev_priv, false);
-
- intel_csr_ucode_init(dev_priv);
-
- ret = intel_irq_install(dev_priv);
- if (ret)
- goto cleanup_csr;
-
- intel_setup_gmbus(dev);
-
- /* Important: The output setup functions called by modeset_init need
- * working irqs for e.g. gmbus and dp aux transfers. */
- intel_modeset_init(dev);
-
- intel_guc_ucode_init(dev);
-
- ret = i915_gem_init(dev);
- if (ret)
- goto cleanup_irq;
-
- intel_modeset_gem_init(dev);
-
- if (INTEL_INFO(dev)->num_pipes == 0)
- return 0;
-
- ret = intel_fbdev_init(dev);
- if (ret)
- goto cleanup_gem;
-
- /* Only enable hotplug handling once the fbdev is fully set up. */
- intel_hpd_init(dev_priv);
-
- /*
- * Some ports require correctly set-up hpd registers for detection to
- * work properly (leading to ghost connected connector status), e.g. VGA
- * on gm45. Hence we can only set up the initial fbdev config after hpd
- * irqs are fully enabled. Now we should scan for the initial config
- * only once hotplug handling is enabled, but due to screwed-up locking
- * around kms/fbdev init we can't protect the fdbev initial config
- * scanning against hotplug events. Hence do this first and ignore the
- * tiny window where we will loose hotplug notifactions.
- */
- intel_fbdev_initial_config_async(dev);
-
- drm_kms_helper_poll_init(dev);
-
- return 0;
-
-cleanup_gem:
- mutex_lock(&dev->struct_mutex);
- i915_gem_cleanup_engines(dev);
- i915_gem_context_fini(dev);
- mutex_unlock(&dev->struct_mutex);
-cleanup_irq:
- intel_guc_ucode_fini(dev);
- drm_irq_uninstall(dev);
- intel_teardown_gmbus(dev);
-cleanup_csr:
- intel_csr_ucode_fini(dev_priv);
- intel_power_domains_fini(dev_priv);
- vga_switcheroo_unregister_client(dev->pdev);
-cleanup_vga_client:
- vga_client_register(dev->pdev, NULL, NULL, NULL);
-out:
- return ret;
-}
-
-#if IS_ENABLED(CONFIG_FB)
-static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
-{
- struct apertures_struct *ap;
- struct pci_dev *pdev = dev_priv->dev->pdev;
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
- bool primary;
- int ret;
-
- ap = alloc_apertures(1);
- if (!ap)
- return -ENOMEM;
-
- ap->ranges[0].base = ggtt->mappable_base;
- ap->ranges[0].size = ggtt->mappable_end;
-
- primary =
- pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-
- ret = remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
-
- kfree(ap);
-
- return ret;
-}
-#else
-static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
-{
- return 0;
-}
-#endif
-
-#if !defined(CONFIG_VGA_CONSOLE)
-static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
-{
- return 0;
-}
-#elif !defined(CONFIG_DUMMY_CONSOLE)
-static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
-{
- return -ENODEV;
-}
-#else
-static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
-{
- int ret = 0;
-
- DRM_INFO("Replacing VGA console driver\n");
-
- console_lock();
- if (con_is_bound(&vga_con))
- ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
- if (ret == 0) {
- ret = do_unregister_con_driver(&vga_con);
-
- /* Ignore "already unregistered". */
- if (ret == -ENODEV)
- ret = 0;
- }
- console_unlock();
-
- return ret;
-}
-#endif
-
-static void i915_dump_device_info(struct drm_i915_private *dev_priv)
-{
- const struct intel_device_info *info = &dev_priv->info;
-
-#define PRINT_S(name) "%s"
-#define SEP_EMPTY
-#define PRINT_FLAG(name) info->name ? #name "," : ""
-#define SEP_COMMA ,
- DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
- DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
- info->gen,
- dev_priv->dev->pdev->device,
- dev_priv->dev->pdev->revision,
- DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
-#undef PRINT_S
-#undef SEP_EMPTY
-#undef PRINT_FLAG
-#undef SEP_COMMA
-}
-
-static void cherryview_sseu_info_init(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_device_info *info;
- u32 fuse, eu_dis;
-
- info = (struct intel_device_info *)&dev_priv->info;
- fuse = I915_READ(CHV_FUSE_GT);
-
- info->slice_total = 1;
-
- if (!(fuse & CHV_FGT_DISABLE_SS0)) {
- info->subslice_per_slice++;
- eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK |
- CHV_FGT_EU_DIS_SS0_R1_MASK);
- info->eu_total += 8 - hweight32(eu_dis);
- }
-
- if (!(fuse & CHV_FGT_DISABLE_SS1)) {
- info->subslice_per_slice++;
- eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK |
- CHV_FGT_EU_DIS_SS1_R1_MASK);
- info->eu_total += 8 - hweight32(eu_dis);
- }
-
- info->subslice_total = info->subslice_per_slice;
- /*
- * CHV expected to always have a uniform distribution of EU
- * across subslices.
- */
- info->eu_per_subslice = info->subslice_total ?
- info->eu_total / info->subslice_total :
- 0;
- /*
- * CHV supports subslice power gating on devices with more than
- * one subslice, and supports EU power gating on devices with
- * more than one EU pair per subslice.
- */
- info->has_slice_pg = 0;
- info->has_subslice_pg = (info->subslice_total > 1);
- info->has_eu_pg = (info->eu_per_subslice > 2);
-}
-
-static void gen9_sseu_info_init(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_device_info *info;
- int s_max = 3, ss_max = 4, eu_max = 8;
- int s, ss;
- u32 fuse2, s_enable, ss_disable, eu_disable;
- u8 eu_mask = 0xff;
-
- info = (struct intel_device_info *)&dev_priv->info;
- fuse2 = I915_READ(GEN8_FUSE2);
- s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >>
- GEN8_F2_S_ENA_SHIFT;
- ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >>
- GEN9_F2_SS_DIS_SHIFT;
-
- info->slice_total = hweight32(s_enable);
- /*
- * The subslice disable field is global, i.e. it applies
- * to each of the enabled slices.
- */
- info->subslice_per_slice = ss_max - hweight32(ss_disable);
- info->subslice_total = info->slice_total *
- info->subslice_per_slice;
-
- /*
- * Iterate through enabled slices and subslices to
- * count the total enabled EU.
- */
- for (s = 0; s < s_max; s++) {
- if (!(s_enable & (0x1 << s)))
- /* skip disabled slice */
- continue;
-
- eu_disable = I915_READ(GEN9_EU_DISABLE(s));
- for (ss = 0; ss < ss_max; ss++) {
- int eu_per_ss;
-
- if (ss_disable & (0x1 << ss))
- /* skip disabled subslice */
- continue;
-
- eu_per_ss = eu_max - hweight8((eu_disable >> (ss*8)) &
- eu_mask);
-
- /*
- * Record which subslice(s) has(have) 7 EUs. we
- * can tune the hash used to spread work among
- * subslices if they are unbalanced.
- */
- if (eu_per_ss == 7)
- info->subslice_7eu[s] |= 1 << ss;
-
- info->eu_total += eu_per_ss;
- }
- }
-
- /*
- * SKL is expected to always have a uniform distribution
- * of EU across subslices with the exception that any one
- * EU in any one subslice may be fused off for die
- * recovery. BXT is expected to be perfectly uniform in EU
- * distribution.
- */
- info->eu_per_subslice = info->subslice_total ?
- DIV_ROUND_UP(info->eu_total,
- info->subslice_total) : 0;
- /*
- * SKL supports slice power gating on devices with more than
- * one slice, and supports EU power gating on devices with
- * more than one EU pair per subslice. BXT supports subslice
- * power gating on devices with more than one subslice, and
- * supports EU power gating on devices with more than one EU
- * pair per subslice.
- */
- info->has_slice_pg = ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
- (info->slice_total > 1));
- info->has_subslice_pg = (IS_BROXTON(dev) && (info->subslice_total > 1));
- info->has_eu_pg = (info->eu_per_subslice > 2);
-}
-
-static void broadwell_sseu_info_init(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_device_info *info;
- const int s_max = 3, ss_max = 3, eu_max = 8;
- int s, ss;
- u32 fuse2, eu_disable[s_max], s_enable, ss_disable;
-
- fuse2 = I915_READ(GEN8_FUSE2);
- s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
- ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT;
-
- eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK;
- eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) |
- ((I915_READ(GEN8_EU_DISABLE1) & GEN8_EU_DIS1_S1_MASK) <<
- (32 - GEN8_EU_DIS0_S1_SHIFT));
- eu_disable[2] = (I915_READ(GEN8_EU_DISABLE1) >> GEN8_EU_DIS1_S2_SHIFT) |
- ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) <<
- (32 - GEN8_EU_DIS1_S2_SHIFT));
-
-
- info = (struct intel_device_info *)&dev_priv->info;
- info->slice_total = hweight32(s_enable);
-
- /*
- * The subslice disable field is global, i.e. it applies
- * to each of the enabled slices.
- */
- info->subslice_per_slice = ss_max - hweight32(ss_disable);
- info->subslice_total = info->slice_total * info->subslice_per_slice;
-
- /*
- * Iterate through enabled slices and subslices to
- * count the total enabled EU.
- */
- for (s = 0; s < s_max; s++) {
- if (!(s_enable & (0x1 << s)))
- /* skip disabled slice */
- continue;
-
- for (ss = 0; ss < ss_max; ss++) {
- u32 n_disabled;
-
- if (ss_disable & (0x1 << ss))
- /* skip disabled subslice */
- continue;
-
- n_disabled = hweight8(eu_disable[s] >> (ss * eu_max));
-
- /*
- * Record which subslices have 7 EUs.
- */
- if (eu_max - n_disabled == 7)
- info->subslice_7eu[s] |= 1 << ss;
-
- info->eu_total += eu_max - n_disabled;
- }
- }
-
- /*
- * BDW is expected to always have a uniform distribution of EU across
- * subslices with the exception that any one EU in any one subslice may
- * be fused off for die recovery.
- */
- info->eu_per_subslice = info->subslice_total ?
- DIV_ROUND_UP(info->eu_total, info->subslice_total) : 0;
-
- /*
- * BDW supports slice power gating on devices with more than
- * one slice.
- */
- info->has_slice_pg = (info->slice_total > 1);
- info->has_subslice_pg = 0;
- info->has_eu_pg = 0;
-}
-
-/*
- * Determine various intel_device_info fields at runtime.
- *
- * Use it when either:
- * - it's judged too laborious to fill n static structures with the limit
- * when a simple if statement does the job,
- * - run-time checks (eg read fuse/strap registers) are needed.
- *
- * This function needs to be called:
- * - after the MMIO has been setup as we are reading registers,
- * - after the PCH has been detected,
- * - before the first usage of the fields it can tweak.
- */
-static void intel_device_info_runtime_init(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_device_info *info;
- enum pipe pipe;
-
- info = (struct intel_device_info *)&dev_priv->info;
-
- /*
- * Skylake and Broxton currently don't expose the topmost plane as its
- * use is exclusive with the legacy cursor and we only want to expose
- * one of those, not both. Until we can safely expose the topmost plane
- * as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported,
- * we don't expose the topmost plane at all to prevent ABI breakage
- * down the line.
- */
- if (IS_BROXTON(dev)) {
- info->num_sprites[PIPE_A] = 2;
- info->num_sprites[PIPE_B] = 2;
- info->num_sprites[PIPE_C] = 1;
- } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
- for_each_pipe(dev_priv, pipe)
- info->num_sprites[pipe] = 2;
- else
- for_each_pipe(dev_priv, pipe)
- info->num_sprites[pipe] = 1;
-
- if (i915.disable_display) {
- DRM_INFO("Display disabled (module parameter)\n");
- info->num_pipes = 0;
- } else if (info->num_pipes > 0 &&
- (INTEL_INFO(dev)->gen == 7 || INTEL_INFO(dev)->gen == 8) &&
- HAS_PCH_SPLIT(dev)) {
- u32 fuse_strap = I915_READ(FUSE_STRAP);
- u32 sfuse_strap = I915_READ(SFUSE_STRAP);
-
- /*
- * SFUSE_STRAP is supposed to have a bit signalling the display
- * is fused off. Unfortunately it seems that, at least in
- * certain cases, fused off display means that PCH display
- * reads don't land anywhere. In that case, we read 0s.
- *
- * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK
- * should be set when taking over after the firmware.
- */
- if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
- sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
- (dev_priv->pch_type == PCH_CPT &&
- !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
- DRM_INFO("Display fused off, disabling\n");
- info->num_pipes = 0;
- } else if (fuse_strap & IVB_PIPE_C_DISABLE) {
- DRM_INFO("PipeC fused off\n");
- info->num_pipes -= 1;
- }
- } else if (info->num_pipes > 0 && INTEL_INFO(dev)->gen == 9) {
- u32 dfsm = I915_READ(SKL_DFSM);
- u8 disabled_mask = 0;
- bool invalid;
- int num_bits;
-
- if (dfsm & SKL_DFSM_PIPE_A_DISABLE)
- disabled_mask |= BIT(PIPE_A);
- if (dfsm & SKL_DFSM_PIPE_B_DISABLE)
- disabled_mask |= BIT(PIPE_B);
- if (dfsm & SKL_DFSM_PIPE_C_DISABLE)
- disabled_mask |= BIT(PIPE_C);
-
- num_bits = hweight8(disabled_mask);
-
- switch (disabled_mask) {
- case BIT(PIPE_A):
- case BIT(PIPE_B):
- case BIT(PIPE_A) | BIT(PIPE_B):
- case BIT(PIPE_A) | BIT(PIPE_C):
- invalid = true;
- break;
- default:
- invalid = false;
- }
-
- if (num_bits > info->num_pipes || invalid)
- DRM_ERROR("invalid pipe fuse configuration: 0x%x\n",
- disabled_mask);
- else
- info->num_pipes -= num_bits;
- }
-
- /* Initialize slice/subslice/EU info */
- if (IS_CHERRYVIEW(dev))
- cherryview_sseu_info_init(dev);
- else if (IS_BROADWELL(dev))
- broadwell_sseu_info_init(dev);
- else if (INTEL_INFO(dev)->gen >= 9)
- gen9_sseu_info_init(dev);
-
- /* Snooping is broken on BXT A stepping. */
- info->has_snoop = !info->has_llc;
- info->has_snoop &= !IS_BXT_REVID(dev, 0, BXT_REVID_A1);
-
- DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total);
- DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total);
- DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice);
- DRM_DEBUG_DRIVER("EU total: %u\n", info->eu_total);
- DRM_DEBUG_DRIVER("EU per subslice: %u\n", info->eu_per_subslice);
- DRM_DEBUG_DRIVER("has slice power gating: %s\n",
- info->has_slice_pg ? "y" : "n");
- DRM_DEBUG_DRIVER("has subslice power gating: %s\n",
- info->has_subslice_pg ? "y" : "n");
- DRM_DEBUG_DRIVER("has EU power gating: %s\n",
- info->has_eu_pg ? "y" : "n");
-}
-
-static void intel_init_dpio(struct drm_i915_private *dev_priv)
-{
- /*
- * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
- * CHV x1 PHY (DP/HDMI D)
- * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
- */
- if (IS_CHERRYVIEW(dev_priv)) {
- DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
- DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
- } else if (IS_VALLEYVIEW(dev_priv)) {
- DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
- }
-}
-
-static int i915_workqueues_init(struct drm_i915_private *dev_priv)
-{
- /*
- * The i915 workqueue is primarily used for batched retirement of
- * requests (and thus managing bo) once the task has been completed
- * by the GPU. i915_gem_retire_requests() is called directly when we
- * need high-priority retirement, such as waiting for an explicit
- * bo.
- *
- * It is also used for periodic low-priority events, such as
- * idle-timers and recording error state.
- *
- * All tasks on the workqueue are expected to acquire the dev mutex
- * so there is no point in running more than one instance of the
- * workqueue at any time. Use an ordered one.
- */
- dev_priv->wq = alloc_ordered_workqueue("i915", 0);
- if (dev_priv->wq == NULL)
- goto out_err;
-
- dev_priv->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0);
- if (dev_priv->hotplug.dp_wq == NULL)
- goto out_free_wq;
-
- dev_priv->gpu_error.hangcheck_wq =
- alloc_ordered_workqueue("i915-hangcheck", 0);
- if (dev_priv->gpu_error.hangcheck_wq == NULL)
- goto out_free_dp_wq;
-
- return 0;
-
-out_free_dp_wq:
- destroy_workqueue(dev_priv->hotplug.dp_wq);
-out_free_wq:
- destroy_workqueue(dev_priv->wq);
-out_err:
- DRM_ERROR("Failed to allocate workqueues.\n");
-
- return -ENOMEM;
-}
-
-static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
-{
- destroy_workqueue(dev_priv->gpu_error.hangcheck_wq);
- destroy_workqueue(dev_priv->hotplug.dp_wq);
- destroy_workqueue(dev_priv->wq);
-}
-
-/**
- * i915_driver_init_early - setup state not requiring device access
- * @dev_priv: device private
- *
- * Initialize everything that is a "SW-only" state, that is state not
- * requiring accessing the device or exposing the driver via kernel internal
- * or userspace interfaces. Example steps belonging here: lock initialization,
- * system memory allocation, setting up device specific attributes and
- * function hooks not requiring accessing the device.
- */
-static int i915_driver_init_early(struct drm_i915_private *dev_priv,
- struct drm_device *dev,
- struct intel_device_info *info)
-{
- struct intel_device_info *device_info;
- int ret = 0;
-
- if (i915_inject_load_failure())
- return -ENODEV;
-
- /* Setup the write-once "constant" device info */
- device_info = (struct intel_device_info *)&dev_priv->info;
- memcpy(device_info, info, sizeof(dev_priv->info));
- device_info->device_id = dev->pdev->device;
-
- spin_lock_init(&dev_priv->irq_lock);
- spin_lock_init(&dev_priv->gpu_error.lock);
- mutex_init(&dev_priv->backlight_lock);
- spin_lock_init(&dev_priv->uncore.lock);
- spin_lock_init(&dev_priv->mm.object_stat_lock);
- spin_lock_init(&dev_priv->mmio_flip_lock);
- mutex_init(&dev_priv->sb_lock);
- mutex_init(&dev_priv->modeset_restore_lock);
- mutex_init(&dev_priv->av_mutex);
- mutex_init(&dev_priv->wm.wm_mutex);
- mutex_init(&dev_priv->pps_mutex);
-
- ret = i915_workqueues_init(dev_priv);
- if (ret < 0)
- return ret;
-
- /* This must be called before any calls to HAS_PCH_* */
- intel_detect_pch(dev);
-
- intel_pm_setup(dev);
- intel_init_dpio(dev_priv);
- intel_power_domains_init(dev_priv);
- intel_irq_init(dev_priv);
- intel_init_display_hooks(dev_priv);
- intel_init_clock_gating_hooks(dev_priv);
- intel_init_audio_hooks(dev_priv);
- i915_gem_load_init(dev);
-
- intel_display_crc_init(dev);
-
- i915_dump_device_info(dev_priv);
-
- /* Not all pre-production machines fall into this category, only the
- * very first ones. Almost everything should work, except for maybe
- * suspend/resume. And we don't implement workarounds that affect only
- * pre-production machines. */
- if (IS_HSW_EARLY_SDV(dev))
- DRM_INFO("This is an early pre-production Haswell machine. "
- "It may not be fully functional.\n");
-
- return 0;
-}
-
-/**
- * i915_driver_cleanup_early - cleanup the setup done in i915_driver_init_early()
- * @dev_priv: device private
- */
-static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
-{
- i915_gem_load_cleanup(dev_priv->dev);
- i915_workqueues_cleanup(dev_priv);
-}
-
-static int i915_mmio_setup(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = to_i915(dev);
- int mmio_bar;
- int mmio_size;
-
- mmio_bar = IS_GEN2(dev) ? 1 : 0;
- /*
- * Before gen4, the registers and the GTT are behind different BARs.
- * However, from gen4 onwards, the registers and the GTT are shared
- * in the same BAR, so we want to restrict this ioremap from
- * clobbering the GTT which we want ioremap_wc instead. Fortunately,
- * the register BAR remains the same size for all the earlier
- * generations up to Ironlake.
- */
- if (INTEL_INFO(dev)->gen < 5)
- mmio_size = 512 * 1024;
- else
- mmio_size = 2 * 1024 * 1024;
- dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, mmio_size);
- if (dev_priv->regs == NULL) {
- DRM_ERROR("failed to map registers\n");
-
- return -EIO;
- }
-
- /* Try to make sure MCHBAR is enabled before poking at it */
- intel_setup_mchbar(dev);
-
- return 0;
-}
-
-static void i915_mmio_cleanup(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- intel_teardown_mchbar(dev);
- pci_iounmap(dev->pdev, dev_priv->regs);
-}
-
-/**
- * i915_driver_init_mmio - setup device MMIO
- * @dev_priv: device private
- *
- * Setup minimal device state necessary for MMIO accesses later in the
- * initialization sequence. The setup here should avoid any other device-wide
- * side effects or exposing the driver via kernel internal or user space
- * interfaces.
- */
-static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
-{
- struct drm_device *dev = dev_priv->dev;
- int ret;
-
- if (i915_inject_load_failure())
- return -ENODEV;
-
- if (i915_get_bridge_dev(dev))
- return -EIO;
-
- ret = i915_mmio_setup(dev);
- if (ret < 0)
- goto put_bridge;
-
- intel_uncore_init(dev);
-
- return 0;
-
-put_bridge:
- pci_dev_put(dev_priv->bridge_dev);
-
- return ret;
-}
-
-/**
- * i915_driver_cleanup_mmio - cleanup the setup done in i915_driver_init_mmio()
- * @dev_priv: device private
- */
-static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
-{
- struct drm_device *dev = dev_priv->dev;
-
- intel_uncore_fini(dev);
- i915_mmio_cleanup(dev);
- pci_dev_put(dev_priv->bridge_dev);
-}
-
-/**
- * i915_driver_init_hw - setup state requiring device access
- * @dev_priv: device private
- *
- * Setup state that requires accessing the device, but doesn't require
- * exposing the driver via kernel internal or userspace interfaces.
- */
-static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
-{
- struct drm_device *dev = dev_priv->dev;
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
- uint32_t aperture_size;
- int ret;
-
- if (i915_inject_load_failure())
- return -ENODEV;
-
- intel_device_info_runtime_init(dev);
-
- ret = i915_ggtt_init_hw(dev);
- if (ret)
- return ret;
-
- ret = i915_ggtt_enable_hw(dev);
- if (ret) {
- DRM_ERROR("failed to enable GGTT\n");
- goto out_ggtt;
- }
-
- /* WARNING: Apparently we must kick fbdev drivers before vgacon,
- * otherwise the vga fbdev driver falls over. */
- ret = i915_kick_out_firmware_fb(dev_priv);
- if (ret) {
- DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
- goto out_ggtt;
- }
-
- ret = i915_kick_out_vgacon(dev_priv);
- if (ret) {
- DRM_ERROR("failed to remove conflicting VGA console\n");
- goto out_ggtt;
- }
-
- pci_set_master(dev->pdev);
-
- /* overlay on gen2 is broken and can't address above 1G */
- if (IS_GEN2(dev))
- dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30));
-
- /* 965GM sometimes incorrectly writes to hardware status page (HWS)
- * using 32bit addressing, overwriting memory if HWS is located
- * above 4GB.
- *
- * The documentation also mentions an issue with undefined
- * behaviour if any general state is accessed within a page above 4GB,
- * which also needs to be handled carefully.
- */
- if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
- dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
-
- aperture_size = ggtt->mappable_end;
-
- ggtt->mappable =
- io_mapping_create_wc(ggtt->mappable_base,
- aperture_size);
- if (!ggtt->mappable) {
- ret = -EIO;
- goto out_ggtt;
- }
-
- ggtt->mtrr = arch_phys_wc_add(ggtt->mappable_base,
- aperture_size);
-
- pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY,
- PM_QOS_DEFAULT_VALUE);
-
- intel_uncore_sanitize(dev);
-
- intel_opregion_setup(dev);
-
- i915_gem_load_init_fences(dev_priv);
-
- /* On the 945G/GM, the chipset reports the MSI capability on the
- * integrated graphics even though the support isn't actually there
- * according to the published specs. It doesn't appear to function
- * correctly in testing on 945G.
- * This may be a side effect of MSI having been made available for PEG
- * and the registers being closely associated.
- *
- * According to chipset errata, on the 965GM, MSI interrupts may
- * be lost or delayed, but we use them anyways to avoid
- * stuck interrupts on some machines.
- */
- if (!IS_I945G(dev) && !IS_I945GM(dev)) {
- if (pci_enable_msi(dev->pdev) < 0)
- DRM_DEBUG_DRIVER("can't enable MSI");
- }
-
- return 0;
-
-out_ggtt:
- i915_ggtt_cleanup_hw(dev);
-
- return ret;
-}
-
-/**
- * i915_driver_cleanup_hw - cleanup the setup done in i915_driver_init_hw()
- * @dev_priv: device private
- */
-static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
-{
- struct drm_device *dev = dev_priv->dev;
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
-
- if (dev->pdev->msi_enabled)
- pci_disable_msi(dev->pdev);
-
- pm_qos_remove_request(&dev_priv->pm_qos);
- arch_phys_wc_del(ggtt->mtrr);
- io_mapping_free(ggtt->mappable);
- i915_ggtt_cleanup_hw(dev);
-}
-
-/**
- * i915_driver_register - register the driver with the rest of the system
- * @dev_priv: device private
- *
- * Perform any steps necessary to make the driver available via kernel
- * internal or userspace interfaces.
- */
-static void i915_driver_register(struct drm_i915_private *dev_priv)
-{
- struct drm_device *dev = dev_priv->dev;
-
- i915_gem_shrinker_init(dev_priv);
- /*
- * Notify a valid surface after modesetting,
- * when running inside a VM.
- */
- if (intel_vgpu_active(dev))
- I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
-
- i915_setup_sysfs(dev);
-
- if (INTEL_INFO(dev_priv)->num_pipes) {
- /* Must be done after probing outputs */
- intel_opregion_init(dev);
- acpi_video_register();
- }
-
- if (IS_GEN5(dev_priv))
- intel_gpu_ips_init(dev_priv);
-
- i915_audio_component_init(dev_priv);
-}
-
-/**
- * i915_driver_unregister - cleanup the registration done in i915_driver_regiser()
- * @dev_priv: device private
- */
-static void i915_driver_unregister(struct drm_i915_private *dev_priv)
-{
- i915_audio_component_cleanup(dev_priv);
- intel_gpu_ips_teardown();
- acpi_video_unregister();
- intel_opregion_fini(dev_priv->dev);
- i915_teardown_sysfs(dev_priv->dev);
- i915_gem_shrinker_cleanup(dev_priv);
-}
-
-/**
- * i915_driver_load - setup chip and create an initial config
- * @dev: DRM device
- * @flags: startup flags
- *
- * The driver load routine has to do several things:
- * - drive output discovery via intel_modeset_init()
- * - initialize the memory manager
- * - allocate initial config memory
- * - setup the DRM framebuffer with the allocated memory
- */
-int i915_driver_load(struct drm_device *dev, unsigned long flags)
-{
- struct drm_i915_private *dev_priv;
- int ret = 0;
-
- dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
- if (dev_priv == NULL)
- return -ENOMEM;
-
- dev->dev_private = dev_priv;
- /* Must be set before calling __i915_printk */
- dev_priv->dev = dev;
-
- ret = i915_driver_init_early(dev_priv, dev,
- (struct intel_device_info *)flags);
-
- if (ret < 0)
- goto out_free_priv;
-
- intel_runtime_pm_get(dev_priv);
-
- ret = i915_driver_init_mmio(dev_priv);
- if (ret < 0)
- goto out_runtime_pm_put;
-
- ret = i915_driver_init_hw(dev_priv);
- if (ret < 0)
- goto out_cleanup_mmio;
-
- /*
- * TODO: move the vblank init and parts of modeset init steps into one
- * of the i915_driver_init_/i915_driver_register functions according
- * to the role/effect of the given init step.
- */
- if (INTEL_INFO(dev)->num_pipes) {
- ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
- if (ret)
- goto out_cleanup_hw;
- }
-
- ret = i915_load_modeset_init(dev);
- if (ret < 0)
- goto out_cleanup_vblank;
-
- i915_driver_register(dev_priv);
-
- intel_runtime_pm_enable(dev_priv);
-
- intel_runtime_pm_put(dev_priv);
-
- return 0;
-
-out_cleanup_vblank:
- drm_vblank_cleanup(dev);
-out_cleanup_hw:
- i915_driver_cleanup_hw(dev_priv);
-out_cleanup_mmio:
- i915_driver_cleanup_mmio(dev_priv);
-out_runtime_pm_put:
- intel_runtime_pm_put(dev_priv);
- i915_driver_cleanup_early(dev_priv);
-out_free_priv:
- i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
-
- kfree(dev_priv);
-
- return ret;
-}
-
-int i915_driver_unload(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int ret;
-
- intel_fbdev_fini(dev);
-
- ret = i915_gem_suspend(dev);
- if (ret) {
- DRM_ERROR("failed to idle hardware: %d\n", ret);
- return ret;
- }
-
- intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
-
- i915_driver_unregister(dev_priv);
-
- drm_vblank_cleanup(dev);
-
- intel_modeset_cleanup(dev);
-
- /*
- * free the memory space allocated for the child device
- * config parsed from VBT
- */
- if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) {
- kfree(dev_priv->vbt.child_dev);
- dev_priv->vbt.child_dev = NULL;
- dev_priv->vbt.child_dev_num = 0;
- }
- kfree(dev_priv->vbt.sdvo_lvds_vbt_mode);
- dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
- kfree(dev_priv->vbt.lfp_lvds_vbt_mode);
- dev_priv->vbt.lfp_lvds_vbt_mode = NULL;
-
- vga_switcheroo_unregister_client(dev->pdev);
- vga_client_register(dev->pdev, NULL, NULL, NULL);
-
- intel_csr_ucode_fini(dev_priv);
-
- /* Free error state after interrupts are fully disabled. */
- cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
- i915_destroy_error_state(dev);
-
- /* Flush any outstanding unpin_work. */
- flush_workqueue(dev_priv->wq);
-
- intel_guc_ucode_fini(dev);
- mutex_lock(&dev->struct_mutex);
- i915_gem_cleanup_engines(dev);
- i915_gem_context_fini(dev);
- mutex_unlock(&dev->struct_mutex);
- intel_fbc_cleanup_cfb(dev_priv);
-
- intel_power_domains_fini(dev_priv);
-
- i915_driver_cleanup_hw(dev_priv);
- i915_driver_cleanup_mmio(dev_priv);
-
- intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
-
- i915_driver_cleanup_early(dev_priv);
- kfree(dev_priv);
-
- return 0;
-}
-
-int i915_driver_open(struct drm_device *dev, struct drm_file *file)
-{
- int ret;
-
- ret = i915_gem_open(dev, file);
- if (ret)
- return ret;
-
- return 0;
-}
-
-/**
- * i915_driver_lastclose - clean up after all DRM clients have exited
- * @dev: DRM device
- *
- * Take care of cleaning up after all DRM clients have exited. In the
- * mode setting case, we want to restore the kernel's initial mode (just
- * in case the last client left us in a bad state).
- *
- * Additionally, in the non-mode setting case, we'll tear down the GTT
- * and DMA structures, since the kernel won't be using them, and clea
- * up any GEM state.
- */
-void i915_driver_lastclose(struct drm_device *dev)
-{
- intel_fbdev_restore_mode(dev);
- vga_switcheroo_process_delayed_switch();
-}
-
-void i915_driver_preclose(struct drm_device *dev, struct drm_file *file)
-{
- mutex_lock(&dev->struct_mutex);
- i915_gem_context_close(dev, file);
- i915_gem_release(dev, file);
- mutex_unlock(&dev->struct_mutex);
-}
-
-void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
-{
- struct drm_i915_file_private *file_priv = file->driver_priv;
-
- kfree(file_priv);
-}
-
-static int
-i915_gem_reject_pin_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- return -ENODEV;
-}
-
-const struct drm_ioctl_desc i915_ioctls[] = {
- DRM_IOCTL_DEF_DRV(I915_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_FLUSH, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_FLIP, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_BATCHBUFFER, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_SETPARAM, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, drm_noop, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_SET_CACHING, i915_gem_set_caching_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_GET_CACHING, i915_gem_get_caching_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
- DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW),
-};
-
-int i915_max_ioctl = ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
deleted file mode 100644
index 6c927144b..000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * R-Car Display Unit HDMI Connector
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * 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.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_encoder_slave.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_encoder.h"
-#include "rcar_du_hdmicon.h"
-#include "rcar_du_kms.h"
-
-#define to_slave_funcs(e) (to_rcar_encoder(e)->slave.slave_funcs)
-
-static int rcar_du_hdmi_connector_get_modes(struct drm_connector *connector)
-{
- struct rcar_du_connector *con = to_rcar_connector(connector);
- struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(con->encoder);
- const struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
-
- if (sfuncs->get_modes == NULL)
- return 0;
-
- return sfuncs->get_modes(encoder, connector);
-}
-
-static int rcar_du_hdmi_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct rcar_du_connector *con = to_rcar_connector(connector);
- struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(con->encoder);
- const struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
-
- if (sfuncs->mode_valid == NULL)
- return MODE_OK;
-
- return sfuncs->mode_valid(encoder, mode);
-}
-
-static const struct drm_connector_helper_funcs connector_helper_funcs = {
- .get_modes = rcar_du_hdmi_connector_get_modes,
- .mode_valid = rcar_du_hdmi_connector_mode_valid,
- .best_encoder = rcar_du_connector_best_encoder,
-};
-
-static enum drm_connector_status
-rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force)
-{
- struct rcar_du_connector *con = to_rcar_connector(connector);
- struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(con->encoder);
- const struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
-
- if (sfuncs->detect == NULL)
- return connector_status_unknown;
-
- return sfuncs->detect(encoder, connector);
-}
-
-static const struct drm_connector_funcs connector_funcs = {
- .dpms = drm_atomic_helper_connector_dpms,
- .reset = drm_atomic_helper_connector_reset,
- .detect = rcar_du_hdmi_connector_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
- struct rcar_du_encoder *renc)
-{
- struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
- struct rcar_du_connector *rcon;
- struct drm_connector *connector;
- int ret;
-
- rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
- if (rcon == NULL)
- return -ENOMEM;
-
- connector = &rcon->connector;
- connector->display_info.width_mm = 0;
- connector->display_info.height_mm = 0;
- connector->interlace_allowed = true;
- connector->polled = DRM_CONNECTOR_POLL_HPD;
-
- ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA);
- if (ret < 0)
- return ret;
-
- drm_connector_helper_add(connector, &connector_helper_funcs);
-
- connector->dpms = DRM_MODE_DPMS_OFF;
- drm_object_property_set_value(&connector->base,
- rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
-
- ret = drm_mode_connector_attach_encoder(connector, encoder);
- if (ret < 0)
- return ret;
-
- rcon->encoder = renc;
-
- return 0;
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.h b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.h
deleted file mode 100644
index 87daa9492..000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * R-Car Display Unit HDMI Connector
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * 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.
- */
-
-#ifndef __RCAR_DU_HDMICON_H__
-#define __RCAR_DU_HDMICON_H__
-
-struct rcar_du_device;
-struct rcar_du_encoder;
-
-#if IS_ENABLED(CONFIG_DRM_RCAR_HDMI)
-int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
- struct rcar_du_encoder *renc);
-#else
-static inline int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
- struct rcar_du_encoder *renc)
-{
- return -ENOSYS;
-}
-#endif
-
-#endif /* __RCAR_DU_HDMICON_H__ */
diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c
deleted file mode 100644
index 9ad9c6ec5..000000000
--- a/drivers/hid/hid-thingm.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * ThingM blink(1) USB RGB LED driver
- *
- * Copyright 2013-2014 Savoir-faire Linux Inc.
- * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
- *
- * 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, version 2.
- */
-
-#include <linux/hid.h>
-#include <linux/hidraw.h>
-#include <linux/leds.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-
-#include "hid-ids.h"
-
-#define REPORT_ID 1
-#define REPORT_SIZE 9
-
-/* Firmware major number of supported devices */
-#define THINGM_MAJOR_MK1 '1'
-#define THINGM_MAJOR_MK2 '2'
-
-struct thingm_fwinfo {
- char major;
- unsigned numrgb;
- unsigned first;
-};
-
-static const struct thingm_fwinfo thingm_fwinfo[] = {
- {
- .major = THINGM_MAJOR_MK1,
- .numrgb = 1,
- .first = 0,
- }, {
- .major = THINGM_MAJOR_MK2,
- .numrgb = 2,
- .first = 1,
- }
-};
-
-/* A red, green or blue channel, part of an RGB chip */
-struct thingm_led {
- struct thingm_rgb *rgb;
- struct led_classdev ldev;
- char name[32];
-};
-
-/* Basically a WS2812 5050 RGB LED chip */
-struct thingm_rgb {
- struct thingm_device *tdev;
- struct thingm_led red;
- struct thingm_led green;
- struct thingm_led blue;
- u8 num;
-};
-
-struct thingm_device {
- struct hid_device *hdev;
- struct {
- char major;
- char minor;
- } version;
- const struct thingm_fwinfo *fwinfo;
- struct mutex lock;
- struct thingm_rgb *rgb;
-};
-
-static int thingm_send(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
-{
- int ret;
-
- hid_dbg(tdev->hdev, "-> %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n",
- buf[0], buf[1], buf[2], buf[3], buf[4],
- buf[5], buf[6], buf[7], buf[8]);
-
- mutex_lock(&tdev->lock);
-
- ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-
- mutex_unlock(&tdev->lock);
-
- return ret < 0 ? ret : 0;
-}
-
-static int thingm_recv(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
-{
- int ret;
-
- /*
- * A read consists of two operations: sending the read command
- * and the actual read from the device. Use the mutex to protect
- * the full sequence of both operations.
- */
- mutex_lock(&tdev->lock);
-
- ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- if (ret < 0)
- goto err;
-
- ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
- HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
- if (ret < 0)
- goto err;
-
- ret = 0;
-
- hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n",
- buf[0], buf[1], buf[2], buf[3], buf[4],
- buf[5], buf[6], buf[7], buf[8]);
-err:
- mutex_unlock(&tdev->lock);
- return ret;
-}
-
-static int thingm_version(struct thingm_device *tdev)
-{
- u8 buf[REPORT_SIZE] = { REPORT_ID, 'v', 0, 0, 0, 0, 0, 0, 0 };
- int err;
-
- err = thingm_recv(tdev, buf);
- if (err)
- return err;
-
- tdev->version.major = buf[3];
- tdev->version.minor = buf[4];
-
- return 0;
-}
-
-static int thingm_write_color(struct thingm_rgb *rgb)
-{
- u8 buf[REPORT_SIZE] = { REPORT_ID, 'c', 0, 0, 0, 0, 0, rgb->num, 0 };
-
- buf[2] = rgb->red.ldev.brightness;
- buf[3] = rgb->green.ldev.brightness;
- buf[4] = rgb->blue.ldev.brightness;
-
- return thingm_send(rgb->tdev, buf);
-}
-
-static int thingm_led_set(struct led_classdev *ldev,
- enum led_brightness brightness)
-{
- struct thingm_led *led = container_of(ldev, struct thingm_led, ldev);
-
- return thingm_write_color(led->rgb);
-}
-
-static int thingm_init_led(struct thingm_led *led, const char *color_name,
- struct thingm_rgb *rgb, int minor)
-{
- snprintf(led->name, sizeof(led->name), "thingm%d:%s:led%d",
- minor, color_name, rgb->num);
- led->ldev.name = led->name;
- led->ldev.max_brightness = 255;
- led->ldev.brightness_set_blocking = thingm_led_set;
- led->ldev.flags = LED_HW_PLUGGABLE;
- led->rgb = rgb;
- return devm_led_classdev_register(&rgb->tdev->hdev->dev, &led->ldev);
-}
-
-static int thingm_init_rgb(struct thingm_rgb *rgb)
-{
- const int minor = ((struct hidraw *) rgb->tdev->hdev->hidraw)->minor;
- int err;
-
- /* Register the red diode */
- err = thingm_init_led(&rgb->red, "red", rgb, minor);
- if (err)
- return err;
-
- /* Register the green diode */
- err = thingm_init_led(&rgb->green, "green", rgb, minor);
- if (err)
- return err;
-
- /* Register the blue diode */
- return thingm_init_led(&rgb->blue, "blue", rgb, minor);
-}
-
-static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
- struct thingm_device *tdev;
- int i, err;
-
- tdev = devm_kzalloc(&hdev->dev, sizeof(struct thingm_device),
- GFP_KERNEL);
- if (!tdev)
- return -ENOMEM;
-
- tdev->hdev = hdev;
- hid_set_drvdata(hdev, tdev);
-
- err = hid_parse(hdev);
- if (err)
- return err;
-
- mutex_init(&tdev->lock);
-
- err = thingm_version(tdev);
- if (err)
- return err;
-
- hid_dbg(hdev, "firmware version: %c.%c\n",
- tdev->version.major, tdev->version.minor);
-
- for (i = 0; i < ARRAY_SIZE(thingm_fwinfo) && !tdev->fwinfo; ++i)
- if (thingm_fwinfo[i].major == tdev->version.major)
- tdev->fwinfo = &thingm_fwinfo[i];
-
- if (!tdev->fwinfo) {
- hid_err(hdev, "unsupported firmware %c\n", tdev->version.major);
- return -ENODEV;
- }
-
- tdev->rgb = devm_kzalloc(&hdev->dev,
- sizeof(struct thingm_rgb) * tdev->fwinfo->numrgb,
- GFP_KERNEL);
- if (!tdev->rgb)
- return -ENOMEM;
-
- err = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
- if (err)
- return err;
-
- for (i = 0; i < tdev->fwinfo->numrgb; ++i) {
- struct thingm_rgb *rgb = tdev->rgb + i;
-
- rgb->tdev = tdev;
- rgb->num = tdev->fwinfo->first + i;
- err = thingm_init_rgb(rgb);
- if (err) {
- hid_hw_stop(hdev);
- return err;
- }
- }
-
- return 0;
-}
-
-static const struct hid_device_id thingm_table[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
- { }
-};
-MODULE_DEVICE_TABLE(hid, thingm_table);
-
-static struct hid_driver thingm_driver = {
- .name = "thingm",
- .probe = thingm_probe,
- .id_table = thingm_table,
-};
-
-module_hid_driver(thingm_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Vivien Didelot <vivien.didelot@savoirfairelinux.com>");
-MODULE_DESCRIPTION("ThingM blink(1) USB RGB LED driver");
diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
deleted file mode 100644
index df380d55c..000000000
--- a/drivers/hsi/hsi.c
+++ /dev/null
@@ -1,781 +0,0 @@
-/*
- * HSI core.
- *
- * Copyright (C) 2010 Nokia Corporation. All rights reserved.
- *
- * Contact: Carlos Chinea <carlos.chinea@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-#include <linux/hsi/hsi.h>
-#include <linux/compiler.h>
-#include <linux/list.h>
-#include <linux/kobject.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/notifier.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include "hsi_core.h"
-
-static ssize_t modalias_show(struct device *dev,
- struct device_attribute *a __maybe_unused, char *buf)
-{
- return sprintf(buf, "hsi:%s\n", dev_name(dev));
-}
-static DEVICE_ATTR_RO(modalias);
-
-static struct attribute *hsi_bus_dev_attrs[] = {
- &dev_attr_modalias.attr,
- NULL,
-};
-ATTRIBUTE_GROUPS(hsi_bus_dev);
-
-static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev));
-
- return 0;
-}
-
-static int hsi_bus_match(struct device *dev, struct device_driver *driver)
-{
- if (of_driver_match_device(dev, driver))
- return true;
-
- if (strcmp(dev_name(dev), driver->name) == 0)
- return true;
-
- return false;
-}
-
-static struct bus_type hsi_bus_type = {
- .name = "hsi",
- .dev_groups = hsi_bus_dev_groups,
- .match = hsi_bus_match,
- .uevent = hsi_bus_uevent,
-};
-
-static void hsi_client_release(struct device *dev)
-{
- struct hsi_client *cl = to_hsi_client(dev);
-
- kfree(cl->tx_cfg.channels);
- kfree(cl->rx_cfg.channels);
- kfree(cl);
-}
-
-struct hsi_client *hsi_new_client(struct hsi_port *port,
- struct hsi_board_info *info)
-{
- struct hsi_client *cl;
- size_t size;
-
- cl = kzalloc(sizeof(*cl), GFP_KERNEL);
- if (!cl)
- goto err;
-
- cl->tx_cfg = info->tx_cfg;
- if (cl->tx_cfg.channels) {
- size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels);
- cl->tx_cfg.channels = kzalloc(size , GFP_KERNEL);
- if (!cl->tx_cfg.channels)
- goto err_tx;
- memcpy(cl->tx_cfg.channels, info->tx_cfg.channels, size);
- }
-
- cl->rx_cfg = info->rx_cfg;
- if (cl->rx_cfg.channels) {
- size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels);
- cl->rx_cfg.channels = kzalloc(size , GFP_KERNEL);
- if (!cl->rx_cfg.channels)
- goto err_rx;
- memcpy(cl->rx_cfg.channels, info->rx_cfg.channels, size);
- }
-
- cl->device.bus = &hsi_bus_type;
- cl->device.parent = &port->device;
- cl->device.release = hsi_client_release;
- dev_set_name(&cl->device, "%s", info->name);
- cl->device.platform_data = info->platform_data;
- if (info->archdata)
- cl->device.archdata = *info->archdata;
- if (device_register(&cl->device) < 0) {
- pr_err("hsi: failed to register client: %s\n", info->name);
- put_device(&cl->device);
- }
-
- return cl;
-err_rx:
- kfree(cl->tx_cfg.channels);
-err_tx:
- kfree(cl);
-err:
- return NULL;
-}
-EXPORT_SYMBOL_GPL(hsi_new_client);
-
-static void hsi_scan_board_info(struct hsi_controller *hsi)
-{
- struct hsi_cl_info *cl_info;
- struct hsi_port *p;
-
- list_for_each_entry(cl_info, &hsi_board_list, list)
- if (cl_info->info.hsi_id == hsi->id) {
- p = hsi_find_port_num(hsi, cl_info->info.port);
- if (!p)
- continue;
- hsi_new_client(p, &cl_info->info);
- }
-}
-
-#ifdef CONFIG_OF
-static struct hsi_board_info hsi_char_dev_info = {
- .name = "hsi_char",
-};
-
-static int hsi_of_property_parse_mode(struct device_node *client, char *name,
- unsigned int *result)
-{
- const char *mode;
- int err;
-
- err = of_property_read_string(client, name, &mode);
- if (err < 0)
- return err;
-
- if (strcmp(mode, "stream") == 0)
- *result = HSI_MODE_STREAM;
- else if (strcmp(mode, "frame") == 0)
- *result = HSI_MODE_FRAME;
- else
- return -EINVAL;
-
- return 0;
-}
-
-static int hsi_of_property_parse_flow(struct device_node *client, char *name,
- unsigned int *result)
-{
- const char *flow;
- int err;
-
- err = of_property_read_string(client, name, &flow);
- if (err < 0)
- return err;
-
- if (strcmp(flow, "synchronized") == 0)
- *result = HSI_FLOW_SYNC;
- else if (strcmp(flow, "pipeline") == 0)
- *result = HSI_FLOW_PIPE;
- else
- return -EINVAL;
-
- return 0;
-}
-
-static int hsi_of_property_parse_arb_mode(struct device_node *client,
- char *name, unsigned int *result)
-{
- const char *arb_mode;
- int err;
-
- err = of_property_read_string(client, name, &arb_mode);
- if (err < 0)
- return err;
-
- if (strcmp(arb_mode, "round-robin") == 0)
- *result = HSI_ARB_RR;
- else if (strcmp(arb_mode, "priority") == 0)
- *result = HSI_ARB_PRIO;
- else
- return -EINVAL;
-
- return 0;
-}
-
-static void hsi_add_client_from_dt(struct hsi_port *port,
- struct device_node *client)
-{
- struct hsi_client *cl;
- struct hsi_channel channel;
- struct property *prop;
- char name[32];
- int length, cells, err, i, max_chan, mode;
-
- cl = kzalloc(sizeof(*cl), GFP_KERNEL);
- if (!cl)
- return;
-
- err = of_modalias_node(client, name, sizeof(name));
- if (err)
- goto err;
-
- dev_set_name(&cl->device, "%s", name);
-
- err = hsi_of_property_parse_mode(client, "hsi-mode", &mode);
- if (err) {
- err = hsi_of_property_parse_mode(client, "hsi-rx-mode",
- &cl->rx_cfg.mode);
- if (err)
- goto err;
-
- err = hsi_of_property_parse_mode(client, "hsi-tx-mode",
- &cl->tx_cfg.mode);
- if (err)
- goto err;
- } else {
- cl->rx_cfg.mode = mode;
- cl->tx_cfg.mode = mode;
- }
-
- err = of_property_read_u32(client, "hsi-speed-kbps",
- &cl->tx_cfg.speed);
- if (err)
- goto err;
- cl->rx_cfg.speed = cl->tx_cfg.speed;
-
- err = hsi_of_property_parse_flow(client, "hsi-flow",
- &cl->rx_cfg.flow);
- if (err)
- goto err;
-
- err = hsi_of_property_parse_arb_mode(client, "hsi-arb-mode",
- &cl->rx_cfg.arb_mode);
- if (err)
- goto err;
-
- prop = of_find_property(client, "hsi-channel-ids", &length);
- if (!prop) {
- err = -EINVAL;
- goto err;
- }
-
- cells = length / sizeof(u32);
-
- cl->rx_cfg.num_channels = cells;
- cl->tx_cfg.num_channels = cells;
-
- cl->rx_cfg.channels = kzalloc(cells * sizeof(channel), GFP_KERNEL);
- if (!cl->rx_cfg.channels) {
- err = -ENOMEM;
- goto err;
- }
-
- cl->tx_cfg.channels = kzalloc(cells * sizeof(channel), GFP_KERNEL);
- if (!cl->tx_cfg.channels) {
- err = -ENOMEM;
- goto err2;
- }
-
- max_chan = 0;
- for (i = 0; i < cells; i++) {
- err = of_property_read_u32_index(client, "hsi-channel-ids", i,
- &channel.id);
- if (err)
- goto err3;
-
- err = of_property_read_string_index(client, "hsi-channel-names",
- i, &channel.name);
- if (err)
- channel.name = NULL;
-
- if (channel.id > max_chan)
- max_chan = channel.id;
-
- cl->rx_cfg.channels[i] = channel;
- cl->tx_cfg.channels[i] = channel;
- }
-
- cl->rx_cfg.num_hw_channels = max_chan + 1;
- cl->tx_cfg.num_hw_channels = max_chan + 1;
-
- cl->device.bus = &hsi_bus_type;
- cl->device.parent = &port->device;
- cl->device.release = hsi_client_release;
- cl->device.of_node = client;
-
- if (device_register(&cl->device) < 0) {
- pr_err("hsi: failed to register client: %s\n", name);
- put_device(&cl->device);
- }
-
- return;
-
-err3:
- kfree(cl->tx_cfg.channels);
-err2:
- kfree(cl->rx_cfg.channels);
-err:
- kfree(cl);
- pr_err("hsi client: missing or incorrect of property: err=%d\n", err);
-}
-
-void hsi_add_clients_from_dt(struct hsi_port *port, struct device_node *clients)
-{
- struct device_node *child;
-
- /* register hsi-char device */
- hsi_new_client(port, &hsi_char_dev_info);
-
- for_each_available_child_of_node(clients, child)
- hsi_add_client_from_dt(port, child);
-}
-EXPORT_SYMBOL_GPL(hsi_add_clients_from_dt);
-#endif
-
-int hsi_remove_client(struct device *dev, void *data __maybe_unused)
-{
- device_unregister(dev);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(hsi_remove_client);
-
-static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
-{
- device_for_each_child(dev, NULL, hsi_remove_client);
- device_unregister(dev);
-
- return 0;
-}
-
-static void hsi_controller_release(struct device *dev)
-{
- struct hsi_controller *hsi = to_hsi_controller(dev);
-
- kfree(hsi->port);
- kfree(hsi);
-}
-
-static void hsi_port_release(struct device *dev)
-{
- kfree(to_hsi_port(dev));
-}
-
-/**
- * hsi_unregister_port - Unregister an HSI port
- * @port: The HSI port to unregister
- */
-void hsi_port_unregister_clients(struct hsi_port *port)
-{
- device_for_each_child(&port->device, NULL, hsi_remove_client);
-}
-EXPORT_SYMBOL_GPL(hsi_port_unregister_clients);
-
-/**
- * hsi_unregister_controller - Unregister an HSI controller
- * @hsi: The HSI controller to register
- */
-void hsi_unregister_controller(struct hsi_controller *hsi)
-{
- device_for_each_child(&hsi->device, NULL, hsi_remove_port);
- device_unregister(&hsi->device);
-}
-EXPORT_SYMBOL_GPL(hsi_unregister_controller);
-
-/**
- * hsi_register_controller - Register an HSI controller and its ports
- * @hsi: The HSI controller to register
- *
- * Returns -errno on failure, 0 on success.
- */
-int hsi_register_controller(struct hsi_controller *hsi)
-{
- unsigned int i;
- int err;
-
- err = device_add(&hsi->device);
- if (err < 0)
- return err;
- for (i = 0; i < hsi->num_ports; i++) {
- hsi->port[i]->device.parent = &hsi->device;
- err = device_add(&hsi->port[i]->device);
- if (err < 0)
- goto out;
- }
- /* Populate HSI bus with HSI clients */
- hsi_scan_board_info(hsi);
-
- return 0;
-out:
- while (i-- > 0)
- device_del(&hsi->port[i]->device);
- device_del(&hsi->device);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(hsi_register_controller);
-
-/**
- * hsi_register_client_driver - Register an HSI client to the HSI bus
- * @drv: HSI client driver to register
- *
- * Returns -errno on failure, 0 on success.
- */
-int hsi_register_client_driver(struct hsi_client_driver *drv)
-{
- drv->driver.bus = &hsi_bus_type;
-
- return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL_GPL(hsi_register_client_driver);
-
-static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused)
-{
- return 0;
-}
-
-static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
-{
- return 0;
-}
-
-/**
- * hsi_put_controller - Free an HSI controller
- *
- * @hsi: Pointer to the HSI controller to freed
- *
- * HSI controller drivers should only use this function if they need
- * to free their allocated hsi_controller structures before a successful
- * call to hsi_register_controller. Other use is not allowed.
- */
-void hsi_put_controller(struct hsi_controller *hsi)
-{
- unsigned int i;
-
- if (!hsi)
- return;
-
- for (i = 0; i < hsi->num_ports; i++)
- if (hsi->port && hsi->port[i])
- put_device(&hsi->port[i]->device);
- put_device(&hsi->device);
-}
-EXPORT_SYMBOL_GPL(hsi_put_controller);
-
-/**
- * hsi_alloc_controller - Allocate an HSI controller and its ports
- * @n_ports: Number of ports on the HSI controller
- * @flags: Kernel allocation flags
- *
- * Return NULL on failure or a pointer to an hsi_controller on success.
- */
-struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
-{
- struct hsi_controller *hsi;
- struct hsi_port **port;
- unsigned int i;
-
- if (!n_ports)
- return NULL;
-
- hsi = kzalloc(sizeof(*hsi), flags);
- if (!hsi)
- return NULL;
- port = kzalloc(sizeof(*port)*n_ports, flags);
- if (!port) {
- kfree(hsi);
- return NULL;
- }
- hsi->num_ports = n_ports;
- hsi->port = port;
- hsi->device.release = hsi_controller_release;
- device_initialize(&hsi->device);
-
- for (i = 0; i < n_ports; i++) {
- port[i] = kzalloc(sizeof(**port), flags);
- if (port[i] == NULL)
- goto out;
- port[i]->num = i;
- port[i]->async = hsi_dummy_msg;
- port[i]->setup = hsi_dummy_cl;
- port[i]->flush = hsi_dummy_cl;
- port[i]->start_tx = hsi_dummy_cl;
- port[i]->stop_tx = hsi_dummy_cl;
- port[i]->release = hsi_dummy_cl;
- mutex_init(&port[i]->lock);
- ATOMIC_INIT_NOTIFIER_HEAD(&port[i]->n_head);
- dev_set_name(&port[i]->device, "port%d", i);
- hsi->port[i]->device.release = hsi_port_release;
- device_initialize(&hsi->port[i]->device);
- }
-
- return hsi;
-out:
- hsi_put_controller(hsi);
-
- return NULL;
-}
-EXPORT_SYMBOL_GPL(hsi_alloc_controller);
-
-/**
- * hsi_free_msg - Free an HSI message
- * @msg: Pointer to the HSI message
- *
- * Client is responsible to free the buffers pointed by the scatterlists.
- */
-void hsi_free_msg(struct hsi_msg *msg)
-{
- if (!msg)
- return;
- sg_free_table(&msg->sgt);
- kfree(msg);
-}
-EXPORT_SYMBOL_GPL(hsi_free_msg);
-
-/**
- * hsi_alloc_msg - Allocate an HSI message
- * @nents: Number of memory entries
- * @flags: Kernel allocation flags
- *
- * nents can be 0. This mainly makes sense for read transfer.
- * In that case, HSI drivers will call the complete callback when
- * there is data to be read without consuming it.
- *
- * Return NULL on failure or a pointer to an hsi_msg on success.
- */
-struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags)
-{
- struct hsi_msg *msg;
- int err;
-
- msg = kzalloc(sizeof(*msg), flags);
- if (!msg)
- return NULL;
-
- if (!nents)
- return msg;
-
- err = sg_alloc_table(&msg->sgt, nents, flags);
- if (unlikely(err)) {
- kfree(msg);
- msg = NULL;
- }
-
- return msg;
-}
-EXPORT_SYMBOL_GPL(hsi_alloc_msg);
-
-/**
- * hsi_async - Submit an HSI transfer to the controller
- * @cl: HSI client sending the transfer
- * @msg: The HSI transfer passed to controller
- *
- * The HSI message must have the channel, ttype, complete and destructor
- * fields set beforehand. If nents > 0 then the client has to initialize
- * also the scatterlists to point to the buffers to write to or read from.
- *
- * HSI controllers relay on pre-allocated buffers from their clients and they
- * do not allocate buffers on their own.
- *
- * Once the HSI message transfer finishes, the HSI controller calls the
- * complete callback with the status and actual_len fields of the HSI message
- * updated. The complete callback can be called before returning from
- * hsi_async.
- *
- * Returns -errno on failure or 0 on success
- */
-int hsi_async(struct hsi_client *cl, struct hsi_msg *msg)
-{
- struct hsi_port *port = hsi_get_port(cl);
-
- if (!hsi_port_claimed(cl))
- return -EACCES;
-
- WARN_ON_ONCE(!msg->destructor || !msg->complete);
- msg->cl = cl;
-
- return port->async(msg);
-}
-EXPORT_SYMBOL_GPL(hsi_async);
-
-/**
- * hsi_claim_port - Claim the HSI client's port
- * @cl: HSI client that wants to claim its port
- * @share: Flag to indicate if the client wants to share the port or not.
- *
- * Returns -errno on failure, 0 on success.
- */
-int hsi_claim_port(struct hsi_client *cl, unsigned int share)
-{
- struct hsi_port *port = hsi_get_port(cl);
- int err = 0;
-
- mutex_lock(&port->lock);
- if ((port->claimed) && (!port->shared || !share)) {
- err = -EBUSY;
- goto out;
- }
- if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) {
- err = -ENODEV;
- goto out;
- }
- port->claimed++;
- port->shared = !!share;
- cl->pclaimed = 1;
-out:
- mutex_unlock(&port->lock);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(hsi_claim_port);
-
-/**
- * hsi_release_port - Release the HSI client's port
- * @cl: HSI client which previously claimed its port
- */
-void hsi_release_port(struct hsi_client *cl)
-{
- struct hsi_port *port = hsi_get_port(cl);
-
- mutex_lock(&port->lock);
- /* Allow HW driver to do some cleanup */
- port->release(cl);
- if (cl->pclaimed)
- port->claimed--;
- BUG_ON(port->claimed < 0);
- cl->pclaimed = 0;
- if (!port->claimed)
- port->shared = 0;
- module_put(to_hsi_controller(port->device.parent)->owner);
- mutex_unlock(&port->lock);
-}
-EXPORT_SYMBOL_GPL(hsi_release_port);
-
-static int hsi_event_notifier_call(struct notifier_block *nb,
- unsigned long event, void *data __maybe_unused)
-{
- struct hsi_client *cl = container_of(nb, struct hsi_client, nb);
-
- (*cl->ehandler)(cl, event);
-
- return 0;
-}
-
-/**
- * hsi_register_port_event - Register a client to receive port events
- * @cl: HSI client that wants to receive port events
- * @handler: Event handler callback
- *
- * Clients should register a callback to be able to receive
- * events from the ports. Registration should happen after
- * claiming the port.
- * The handler can be called in interrupt context.
- *
- * Returns -errno on error, or 0 on success.
- */
-int hsi_register_port_event(struct hsi_client *cl,
- void (*handler)(struct hsi_client *, unsigned long))
-{
- struct hsi_port *port = hsi_get_port(cl);
-
- if (!handler || cl->ehandler)
- return -EINVAL;
- if (!hsi_port_claimed(cl))
- return -EACCES;
- cl->ehandler = handler;
- cl->nb.notifier_call = hsi_event_notifier_call;
-
- return atomic_notifier_chain_register(&port->n_head, &cl->nb);
-}
-EXPORT_SYMBOL_GPL(hsi_register_port_event);
-
-/**
- * hsi_unregister_port_event - Stop receiving port events for a client
- * @cl: HSI client that wants to stop receiving port events
- *
- * Clients should call this function before releasing their associated
- * port.
- *
- * Returns -errno on error, or 0 on success.
- */
-int hsi_unregister_port_event(struct hsi_client *cl)
-{
- struct hsi_port *port = hsi_get_port(cl);
- int err;
-
- WARN_ON(!hsi_port_claimed(cl));
-
- err = atomic_notifier_chain_unregister(&port->n_head, &cl->nb);
- if (!err)
- cl->ehandler = NULL;
-
- return err;
-}
-EXPORT_SYMBOL_GPL(hsi_unregister_port_event);
-
-/**
- * hsi_event - Notifies clients about port events
- * @port: Port where the event occurred
- * @event: The event type
- *
- * Clients should not be concerned about wake line behavior. However, due
- * to a race condition in HSI HW protocol, clients need to be notified
- * about wake line changes, so they can implement a workaround for it.
- *
- * Events:
- * HSI_EVENT_START_RX - Incoming wake line high
- * HSI_EVENT_STOP_RX - Incoming wake line down
- *
- * Returns -errno on error, or 0 on success.
- */
-int hsi_event(struct hsi_port *port, unsigned long event)
-{
- return atomic_notifier_call_chain(&port->n_head, event, NULL);
-}
-EXPORT_SYMBOL_GPL(hsi_event);
-
-/**
- * hsi_get_channel_id_by_name - acquire channel id by channel name
- * @cl: HSI client, which uses the channel
- * @name: name the channel is known under
- *
- * Clients can call this function to get the hsi channel ids similar to
- * requesting IRQs or GPIOs by name. This function assumes the same
- * channel configuration is used for RX and TX.
- *
- * Returns -errno on error or channel id on success.
- */
-int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name)
-{
- int i;
-
- if (!cl->rx_cfg.channels)
- return -ENOENT;
-
- for (i = 0; i < cl->rx_cfg.num_channels; i++)
- if (!strcmp(cl->rx_cfg.channels[i].name, name))
- return cl->rx_cfg.channels[i].id;
-
- return -ENXIO;
-}
-EXPORT_SYMBOL_GPL(hsi_get_channel_id_by_name);
-
-static int __init hsi_init(void)
-{
- return bus_register(&hsi_bus_type);
-}
-postcore_initcall(hsi_init);
-
-static void __exit hsi_exit(void)
-{
- bus_unregister(&hsi_bus_type);
-}
-module_exit(hsi_exit);
-
-MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
-MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c
deleted file mode 100644
index 724452d61..000000000
--- a/drivers/iio/pressure/bmp280.c
+++ /dev/null
@@ -1,922 +0,0 @@
-/*
- * Copyright (c) 2014 Intel Corporation
- *
- * Driver for Bosch Sensortec BMP180 and BMP280 digital pressure sensor.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Datasheet:
- * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf
- * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf
- */
-
-#define pr_fmt(fmt) "bmp280: " fmt
-
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/acpi.h>
-#include <linux/regmap.h>
-#include <linux/delay.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-
-/* BMP280 specific registers */
-#define BMP280_REG_TEMP_XLSB 0xFC
-#define BMP280_REG_TEMP_LSB 0xFB
-#define BMP280_REG_TEMP_MSB 0xFA
-#define BMP280_REG_PRESS_XLSB 0xF9
-#define BMP280_REG_PRESS_LSB 0xF8
-#define BMP280_REG_PRESS_MSB 0xF7
-
-#define BMP280_REG_CONFIG 0xF5
-#define BMP280_REG_STATUS 0xF3
-
-#define BMP280_REG_COMP_TEMP_START 0x88
-#define BMP280_COMP_TEMP_REG_COUNT 6
-
-#define BMP280_REG_COMP_PRESS_START 0x8E
-#define BMP280_COMP_PRESS_REG_COUNT 18
-
-#define BMP280_FILTER_MASK (BIT(4) | BIT(3) | BIT(2))
-#define BMP280_FILTER_OFF 0
-#define BMP280_FILTER_2X BIT(2)
-#define BMP280_FILTER_4X BIT(3)
-#define BMP280_FILTER_8X (BIT(3) | BIT(2))
-#define BMP280_FILTER_16X BIT(4)
-
-#define BMP280_OSRS_TEMP_MASK (BIT(7) | BIT(6) | BIT(5))
-#define BMP280_OSRS_TEMP_SKIP 0
-#define BMP280_OSRS_TEMP_X(osrs_t) ((osrs_t) << 5)
-#define BMP280_OSRS_TEMP_1X BMP280_OSRS_TEMP_X(1)
-#define BMP280_OSRS_TEMP_2X BMP280_OSRS_TEMP_X(2)
-#define BMP280_OSRS_TEMP_4X BMP280_OSRS_TEMP_X(3)
-#define BMP280_OSRS_TEMP_8X BMP280_OSRS_TEMP_X(4)
-#define BMP280_OSRS_TEMP_16X BMP280_OSRS_TEMP_X(5)
-
-#define BMP280_OSRS_PRESS_MASK (BIT(4) | BIT(3) | BIT(2))
-#define BMP280_OSRS_PRESS_SKIP 0
-#define BMP280_OSRS_PRESS_X(osrs_p) ((osrs_p) << 2)
-#define BMP280_OSRS_PRESS_1X BMP280_OSRS_PRESS_X(1)
-#define BMP280_OSRS_PRESS_2X BMP280_OSRS_PRESS_X(2)
-#define BMP280_OSRS_PRESS_4X BMP280_OSRS_PRESS_X(3)
-#define BMP280_OSRS_PRESS_8X BMP280_OSRS_PRESS_X(4)
-#define BMP280_OSRS_PRESS_16X BMP280_OSRS_PRESS_X(5)
-
-#define BMP280_MODE_MASK (BIT(1) | BIT(0))
-#define BMP280_MODE_SLEEP 0
-#define BMP280_MODE_FORCED BIT(0)
-#define BMP280_MODE_NORMAL (BIT(1) | BIT(0))
-
-/* BMP180 specific registers */
-#define BMP180_REG_OUT_XLSB 0xF8
-#define BMP180_REG_OUT_LSB 0xF7
-#define BMP180_REG_OUT_MSB 0xF6
-
-#define BMP180_REG_CALIB_START 0xAA
-#define BMP180_REG_CALIB_COUNT 22
-
-#define BMP180_MEAS_SCO BIT(5)
-#define BMP180_MEAS_TEMP (0x0E | BMP180_MEAS_SCO)
-#define BMP180_MEAS_PRESS_X(oss) ((oss) << 6 | 0x14 | BMP180_MEAS_SCO)
-#define BMP180_MEAS_PRESS_1X BMP180_MEAS_PRESS_X(0)
-#define BMP180_MEAS_PRESS_2X BMP180_MEAS_PRESS_X(1)
-#define BMP180_MEAS_PRESS_4X BMP180_MEAS_PRESS_X(2)
-#define BMP180_MEAS_PRESS_8X BMP180_MEAS_PRESS_X(3)
-
-/* BMP180 and BMP280 common registers */
-#define BMP280_REG_CTRL_MEAS 0xF4
-#define BMP280_REG_RESET 0xE0
-#define BMP280_REG_ID 0xD0
-
-#define BMP180_CHIP_ID 0x55
-#define BMP280_CHIP_ID 0x58
-#define BMP280_SOFT_RESET_VAL 0xB6
-
-struct bmp280_data {
- struct i2c_client *client;
- struct mutex lock;
- struct regmap *regmap;
- const struct bmp280_chip_info *chip_info;
-
- /* log of base 2 of oversampling rate */
- u8 oversampling_press;
- u8 oversampling_temp;
-
- /*
- * Carryover value from temperature conversion, used in pressure
- * calculation.
- */
- s32 t_fine;
-};
-
-struct bmp280_chip_info {
- const struct regmap_config *regmap_config;
-
- const int *oversampling_temp_avail;
- int num_oversampling_temp_avail;
-
- const int *oversampling_press_avail;
- int num_oversampling_press_avail;
-
- int (*chip_config)(struct bmp280_data *);
- int (*read_temp)(struct bmp280_data *, int *);
- int (*read_press)(struct bmp280_data *, int *, int *);
-};
-
-/*
- * These enums are used for indexing into the array of compensation
- * parameters for BMP280.
- */
-enum { T1, T2, T3 };
-enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 };
-
-static const struct iio_chan_spec bmp280_channels[] = {
- {
- .type = IIO_PRESSURE,
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
- },
- {
- .type = IIO_TEMP,
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
- },
-};
-
-static bool bmp280_is_writeable_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case BMP280_REG_CONFIG:
- case BMP280_REG_CTRL_MEAS:
- case BMP280_REG_RESET:
- return true;
- default:
- return false;
- };
-}
-
-static bool bmp280_is_volatile_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case BMP280_REG_TEMP_XLSB:
- case BMP280_REG_TEMP_LSB:
- case BMP280_REG_TEMP_MSB:
- case BMP280_REG_PRESS_XLSB:
- case BMP280_REG_PRESS_LSB:
- case BMP280_REG_PRESS_MSB:
- case BMP280_REG_STATUS:
- return true;
- default:
- return false;
- }
-}
-
-static const struct regmap_config bmp280_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
-
- .max_register = BMP280_REG_TEMP_XLSB,
- .cache_type = REGCACHE_RBTREE,
-
- .writeable_reg = bmp280_is_writeable_reg,
- .volatile_reg = bmp280_is_volatile_reg,
-};
-
-/*
- * Returns temperature in DegC, resolution is 0.01 DegC. Output value of
- * "5123" equals 51.23 DegC. t_fine carries fine temperature as global
- * value.
- *
- * Taken from datasheet, Section 3.11.3, "Compensation formula".
- */
-static s32 bmp280_compensate_temp(struct bmp280_data *data,
- s32 adc_temp)
-{
- int ret;
- s32 var1, var2;
- __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2];
-
- ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
- buf, BMP280_COMP_TEMP_REG_COUNT);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "failed to read temperature calibration parameters\n");
- return ret;
- }
-
- /*
- * The double casts are necessary because le16_to_cpu returns an
- * unsigned 16-bit value. Casting that value directly to a
- * signed 32-bit will not do proper sign extension.
- *
- * Conversely, T1 and P1 are unsigned values, so they can be
- * cast straight to the larger type.
- */
- var1 = (((adc_temp >> 3) - ((s32)le16_to_cpu(buf[T1]) << 1)) *
- ((s32)(s16)le16_to_cpu(buf[T2]))) >> 11;
- var2 = (((((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1]))) *
- ((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1])))) >> 12) *
- ((s32)(s16)le16_to_cpu(buf[T3]))) >> 14;
- data->t_fine = var1 + var2;
-
- return (data->t_fine * 5 + 128) >> 8;
-}
-
-/*
- * Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24
- * integer bits and 8 fractional bits). Output value of "24674867"
- * represents 24674867/256 = 96386.2 Pa = 963.862 hPa
- *
- * Taken from datasheet, Section 3.11.3, "Compensation formula".
- */
-static u32 bmp280_compensate_press(struct bmp280_data *data,
- s32 adc_press)
-{
- int ret;
- s64 var1, var2, p;
- __le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2];
-
- ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START,
- buf, BMP280_COMP_PRESS_REG_COUNT);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "failed to read pressure calibration parameters\n");
- return ret;
- }
-
- var1 = ((s64)data->t_fine) - 128000;
- var2 = var1 * var1 * (s64)(s16)le16_to_cpu(buf[P6]);
- var2 += (var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17;
- var2 += ((s64)(s16)le16_to_cpu(buf[P4])) << 35;
- var1 = ((var1 * var1 * (s64)(s16)le16_to_cpu(buf[P3])) >> 8) +
- ((var1 * (s64)(s16)le16_to_cpu(buf[P2])) << 12);
- var1 = ((((s64)1) << 47) + var1) * ((s64)le16_to_cpu(buf[P1])) >> 33;
-
- if (var1 == 0)
- return 0;
-
- p = ((((s64)1048576 - adc_press) << 31) - var2) * 3125;
- p = div64_s64(p, var1);
- var1 = (((s64)(s16)le16_to_cpu(buf[P9])) * (p >> 13) * (p >> 13)) >> 25;
- var2 = (((s64)(s16)le16_to_cpu(buf[P8])) * p) >> 19;
- p = ((p + var1 + var2) >> 8) + (((s64)(s16)le16_to_cpu(buf[P7])) << 4);
-
- return (u32)p;
-}
-
-static int bmp280_read_temp(struct bmp280_data *data,
- int *val)
-{
- int ret;
- __be32 tmp = 0;
- s32 adc_temp, comp_temp;
-
- ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
- (u8 *) &tmp, 3);
- if (ret < 0) {
- dev_err(&data->client->dev, "failed to read temperature\n");
- return ret;
- }
-
- adc_temp = be32_to_cpu(tmp) >> 12;
- comp_temp = bmp280_compensate_temp(data, adc_temp);
-
- /*
- * val might be NULL if we're called by the read_press routine,
- * who only cares about the carry over t_fine value.
- */
- if (val) {
- *val = comp_temp * 10;
- return IIO_VAL_INT;
- }
-
- return 0;
-}
-
-static int bmp280_read_press(struct bmp280_data *data,
- int *val, int *val2)
-{
- int ret;
- __be32 tmp = 0;
- s32 adc_press;
- u32 comp_press;
-
- /* Read and compensate temperature so we get a reading of t_fine. */
- ret = bmp280_read_temp(data, NULL);
- if (ret < 0)
- return ret;
-
- ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
- (u8 *) &tmp, 3);
- if (ret < 0) {
- dev_err(&data->client->dev, "failed to read pressure\n");
- return ret;
- }
-
- adc_press = be32_to_cpu(tmp) >> 12;
- comp_press = bmp280_compensate_press(data, adc_press);
-
- *val = comp_press;
- *val2 = 256000;
-
- return IIO_VAL_FRACTIONAL;
-}
-
-static int bmp280_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2, long mask)
-{
- int ret;
- struct bmp280_data *data = iio_priv(indio_dev);
-
- mutex_lock(&data->lock);
-
- switch (mask) {
- case IIO_CHAN_INFO_PROCESSED:
- switch (chan->type) {
- case IIO_PRESSURE:
- ret = data->chip_info->read_press(data, val, val2);
- break;
- case IIO_TEMP:
- ret = data->chip_info->read_temp(data, val);
- break;
- default:
- ret = -EINVAL;
- break;
- }
- break;
- case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- switch (chan->type) {
- case IIO_PRESSURE:
- *val = 1 << data->oversampling_press;
- ret = IIO_VAL_INT;
- break;
- case IIO_TEMP:
- *val = 1 << data->oversampling_temp;
- ret = IIO_VAL_INT;
- break;
- default:
- ret = -EINVAL;
- break;
- }
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- mutex_unlock(&data->lock);
-
- return ret;
-}
-
-static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data,
- int val)
-{
- int i;
- const int *avail = data->chip_info->oversampling_temp_avail;
- const int n = data->chip_info->num_oversampling_temp_avail;
-
- for (i = 0; i < n; i++) {
- if (avail[i] == val) {
- data->oversampling_temp = ilog2(val);
-
- return data->chip_info->chip_config(data);
- }
- }
- return -EINVAL;
-}
-
-static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data,
- int val)
-{
- int i;
- const int *avail = data->chip_info->oversampling_press_avail;
- const int n = data->chip_info->num_oversampling_press_avail;
-
- for (i = 0; i < n; i++) {
- if (avail[i] == val) {
- data->oversampling_press = ilog2(val);
-
- return data->chip_info->chip_config(data);
- }
- }
- return -EINVAL;
-}
-
-static int bmp280_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val, int val2, long mask)
-{
- int ret = 0;
- struct bmp280_data *data = iio_priv(indio_dev);
-
- switch (mask) {
- case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- mutex_lock(&data->lock);
- switch (chan->type) {
- case IIO_PRESSURE:
- ret = bmp280_write_oversampling_ratio_press(data, val);
- break;
- case IIO_TEMP:
- ret = bmp280_write_oversampling_ratio_temp(data, val);
- break;
- default:
- ret = -EINVAL;
- break;
- }
- mutex_unlock(&data->lock);
- break;
- default:
- return -EINVAL;
- }
-
- return ret;
-}
-
-static ssize_t bmp280_show_avail(char *buf, const int *vals, const int n)
-{
- size_t len = 0;
- int i;
-
- for (i = 0; i < n; i++)
- len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", vals[i]);
-
- buf[len - 1] = '\n';
-
- return len;
-}
-
-static ssize_t bmp280_show_temp_oversampling_avail(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
-
- return bmp280_show_avail(buf, data->chip_info->oversampling_temp_avail,
- data->chip_info->num_oversampling_temp_avail);
-}
-
-static ssize_t bmp280_show_press_oversampling_avail(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
-
- return bmp280_show_avail(buf, data->chip_info->oversampling_press_avail,
- data->chip_info->num_oversampling_press_avail);
-}
-
-static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available,
- S_IRUGO, bmp280_show_temp_oversampling_avail, NULL, 0);
-
-static IIO_DEVICE_ATTR(in_pressure_oversampling_ratio_available,
- S_IRUGO, bmp280_show_press_oversampling_avail, NULL, 0);
-
-static struct attribute *bmp280_attributes[] = {
- &iio_dev_attr_in_temp_oversampling_ratio_available.dev_attr.attr,
- &iio_dev_attr_in_pressure_oversampling_ratio_available.dev_attr.attr,
- NULL,
-};
-
-static const struct attribute_group bmp280_attrs_group = {
- .attrs = bmp280_attributes,
-};
-
-static const struct iio_info bmp280_info = {
- .driver_module = THIS_MODULE,
- .read_raw = &bmp280_read_raw,
- .write_raw = &bmp280_write_raw,
- .attrs = &bmp280_attrs_group,
-};
-
-static int bmp280_chip_config(struct bmp280_data *data)
-{
- int ret;
- u8 osrs = BMP280_OSRS_TEMP_X(data->oversampling_temp + 1) |
- BMP280_OSRS_PRESS_X(data->oversampling_press + 1);
-
- ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS,
- BMP280_OSRS_TEMP_MASK |
- BMP280_OSRS_PRESS_MASK |
- BMP280_MODE_MASK,
- osrs | BMP280_MODE_NORMAL);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "failed to write ctrl_meas register\n");
- return ret;
- }
-
- ret = regmap_update_bits(data->regmap, BMP280_REG_CONFIG,
- BMP280_FILTER_MASK,
- BMP280_FILTER_4X);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "failed to write config register\n");
- return ret;
- }
-
- return ret;
-}
-
-static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
-
-static const struct bmp280_chip_info bmp280_chip_info = {
- .regmap_config = &bmp280_regmap_config,
-
- .oversampling_temp_avail = bmp280_oversampling_avail,
- .num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
-
- .oversampling_press_avail = bmp280_oversampling_avail,
- .num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail),
-
- .chip_config = bmp280_chip_config,
- .read_temp = bmp280_read_temp,
- .read_press = bmp280_read_press,
-};
-
-static bool bmp180_is_writeable_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case BMP280_REG_CTRL_MEAS:
- case BMP280_REG_RESET:
- return true;
- default:
- return false;
- };
-}
-
-static bool bmp180_is_volatile_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case BMP180_REG_OUT_XLSB:
- case BMP180_REG_OUT_LSB:
- case BMP180_REG_OUT_MSB:
- case BMP280_REG_CTRL_MEAS:
- return true;
- default:
- return false;
- }
-}
-
-static const struct regmap_config bmp180_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
-
- .max_register = BMP180_REG_OUT_XLSB,
- .cache_type = REGCACHE_RBTREE,
-
- .writeable_reg = bmp180_is_writeable_reg,
- .volatile_reg = bmp180_is_volatile_reg,
-};
-
-static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
-{
- int ret;
- const int conversion_time_max[] = { 4500, 7500, 13500, 25500 };
- unsigned int delay_us;
- unsigned int ctrl;
-
- ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas);
- if (ret)
- return ret;
-
- if (ctrl_meas == BMP180_MEAS_TEMP)
- delay_us = 4500;
- else
- delay_us = conversion_time_max[data->oversampling_press];
-
- usleep_range(delay_us, delay_us + 1000);
-
- ret = regmap_read(data->regmap, BMP280_REG_CTRL_MEAS, &ctrl);
- if (ret)
- return ret;
-
- /* The value of this bit reset to "0" after conversion is complete */
- if (ctrl & BMP180_MEAS_SCO)
- return -EIO;
-
- return 0;
-}
-
-static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
-{
- int ret;
- __be16 tmp = 0;
-
- ret = bmp180_measure(data, BMP180_MEAS_TEMP);
- if (ret)
- return ret;
-
- ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 2);
- if (ret)
- return ret;
-
- *val = be16_to_cpu(tmp);
-
- return 0;
-}
-
-/*
- * These enums are used for indexing into the array of calibration
- * coefficients for BMP180.
- */
-enum { AC1, AC2, AC3, AC4, AC5, AC6, B1, B2, MB, MC, MD };
-
-struct bmp180_calib {
- s16 AC1;
- s16 AC2;
- s16 AC3;
- u16 AC4;
- u16 AC5;
- u16 AC6;
- s16 B1;
- s16 B2;
- s16 MB;
- s16 MC;
- s16 MD;
-};
-
-static int bmp180_read_calib(struct bmp280_data *data,
- struct bmp180_calib *calib)
-{
- int ret;
- int i;
- __be16 buf[BMP180_REG_CALIB_COUNT / 2];
-
- ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf,
- sizeof(buf));
-
- if (ret < 0)
- return ret;
-
- /* None of the words has the value 0 or 0xFFFF */
- for (i = 0; i < ARRAY_SIZE(buf); i++) {
- if (buf[i] == cpu_to_be16(0) || buf[i] == cpu_to_be16(0xffff))
- return -EIO;
- }
-
- calib->AC1 = be16_to_cpu(buf[AC1]);
- calib->AC2 = be16_to_cpu(buf[AC2]);
- calib->AC3 = be16_to_cpu(buf[AC3]);
- calib->AC4 = be16_to_cpu(buf[AC4]);
- calib->AC5 = be16_to_cpu(buf[AC5]);
- calib->AC6 = be16_to_cpu(buf[AC6]);
- calib->B1 = be16_to_cpu(buf[B1]);
- calib->B2 = be16_to_cpu(buf[B2]);
- calib->MB = be16_to_cpu(buf[MB]);
- calib->MC = be16_to_cpu(buf[MC]);
- calib->MD = be16_to_cpu(buf[MD]);
-
- return 0;
-}
-
-/*
- * Returns temperature in DegC, resolution is 0.1 DegC.
- * t_fine carries fine temperature as global value.
- *
- * Taken from datasheet, Section 3.5, "Calculating pressure and temperature".
- */
-static s32 bmp180_compensate_temp(struct bmp280_data *data, s32 adc_temp)
-{
- int ret;
- s32 x1, x2;
- struct bmp180_calib calib;
-
- ret = bmp180_read_calib(data, &calib);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "failed to read calibration coefficients\n");
- return ret;
- }
-
- x1 = ((adc_temp - calib.AC6) * calib.AC5) >> 15;
- x2 = (calib.MC << 11) / (x1 + calib.MD);
- data->t_fine = x1 + x2;
-
- return (data->t_fine + 8) >> 4;
-}
-
-static int bmp180_read_temp(struct bmp280_data *data, int *val)
-{
- int ret;
- s32 adc_temp, comp_temp;
-
- ret = bmp180_read_adc_temp(data, &adc_temp);
- if (ret)
- return ret;
-
- comp_temp = bmp180_compensate_temp(data, adc_temp);
-
- /*
- * val might be NULL if we're called by the read_press routine,
- * who only cares about the carry over t_fine value.
- */
- if (val) {
- *val = comp_temp * 100;
- return IIO_VAL_INT;
- }
-
- return 0;
-}
-
-static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
-{
- int ret;
- __be32 tmp = 0;
- u8 oss = data->oversampling_press;
-
- ret = bmp180_measure(data, BMP180_MEAS_PRESS_X(oss));
- if (ret)
- return ret;
-
- ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 3);
- if (ret)
- return ret;
-
- *val = (be32_to_cpu(tmp) >> 8) >> (8 - oss);
-
- return 0;
-}
-
-/*
- * Returns pressure in Pa, resolution is 1 Pa.
- *
- * Taken from datasheet, Section 3.5, "Calculating pressure and temperature".
- */
-static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press)
-{
- int ret;
- s32 x1, x2, x3, p;
- s32 b3, b6;
- u32 b4, b7;
- s32 oss = data->oversampling_press;
- struct bmp180_calib calib;
-
- ret = bmp180_read_calib(data, &calib);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "failed to read calibration coefficients\n");
- return ret;
- }
-
- b6 = data->t_fine - 4000;
- x1 = (calib.B2 * (b6 * b6 >> 12)) >> 11;
- x2 = calib.AC2 * b6 >> 11;
- x3 = x1 + x2;
- b3 = ((((s32)calib.AC1 * 4 + x3) << oss) + 2) / 4;
- x1 = calib.AC3 * b6 >> 13;
- x2 = (calib.B1 * ((b6 * b6) >> 12)) >> 16;
- x3 = (x1 + x2 + 2) >> 2;
- b4 = calib.AC4 * (u32)(x3 + 32768) >> 15;
- b7 = ((u32)adc_press - b3) * (50000 >> oss);
- if (b7 < 0x80000000)
- p = (b7 * 2) / b4;
- else
- p = (b7 / b4) * 2;
-
- x1 = (p >> 8) * (p >> 8);
- x1 = (x1 * 3038) >> 16;
- x2 = (-7357 * p) >> 16;
-
- return p + ((x1 + x2 + 3791) >> 4);
-}
-
-static int bmp180_read_press(struct bmp280_data *data,
- int *val, int *val2)
-{
- int ret;
- s32 adc_press;
- u32 comp_press;
-
- /* Read and compensate temperature so we get a reading of t_fine. */
- ret = bmp180_read_temp(data, NULL);
- if (ret)
- return ret;
-
- ret = bmp180_read_adc_press(data, &adc_press);
- if (ret)
- return ret;
-
- comp_press = bmp180_compensate_press(data, adc_press);
-
- *val = comp_press;
- *val2 = 1000;
-
- return IIO_VAL_FRACTIONAL;
-}
-
-static int bmp180_chip_config(struct bmp280_data *data)
-{
- return 0;
-}
-
-static const int bmp180_oversampling_temp_avail[] = { 1 };
-static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
-
-static const struct bmp280_chip_info bmp180_chip_info = {
- .regmap_config = &bmp180_regmap_config,
-
- .oversampling_temp_avail = bmp180_oversampling_temp_avail,
- .num_oversampling_temp_avail =
- ARRAY_SIZE(bmp180_oversampling_temp_avail),
-
- .oversampling_press_avail = bmp180_oversampling_press_avail,
- .num_oversampling_press_avail =
- ARRAY_SIZE(bmp180_oversampling_press_avail),
-
- .chip_config = bmp180_chip_config,
- .read_temp = bmp180_read_temp,
- .read_press = bmp180_read_press,
-};
-
-static int bmp280_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- int ret;
- struct iio_dev *indio_dev;
- struct bmp280_data *data;
- unsigned int chip_id;
-
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
- if (!indio_dev)
- return -ENOMEM;
-
- data = iio_priv(indio_dev);
- mutex_init(&data->lock);
- data->client = client;
-
- indio_dev->dev.parent = &client->dev;
- indio_dev->name = id->name;
- indio_dev->channels = bmp280_channels;
- indio_dev->num_channels = ARRAY_SIZE(bmp280_channels);
- indio_dev->info = &bmp280_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
-
- switch (id->driver_data) {
- case BMP180_CHIP_ID:
- data->chip_info = &bmp180_chip_info;
- data->oversampling_press = ilog2(8);
- data->oversampling_temp = ilog2(1);
- break;
- case BMP280_CHIP_ID:
- data->chip_info = &bmp280_chip_info;
- data->oversampling_press = ilog2(16);
- data->oversampling_temp = ilog2(2);
- break;
- default:
- return -EINVAL;
- }
-
- data->regmap = devm_regmap_init_i2c(client,
- data->chip_info->regmap_config);
- if (IS_ERR(data->regmap)) {
- dev_err(&client->dev, "failed to allocate register map\n");
- return PTR_ERR(data->regmap);
- }
-
- ret = regmap_read(data->regmap, BMP280_REG_ID, &chip_id);
- if (ret < 0)
- return ret;
- if (chip_id != id->driver_data) {
- dev_err(&client->dev, "bad chip id. expected %lx got %x\n",
- id->driver_data, chip_id);
- return -EINVAL;
- }
-
- ret = data->chip_info->chip_config(data);
- if (ret < 0)
- return ret;
-
- return devm_iio_device_register(&client->dev, indio_dev);
-}
-
-static const struct acpi_device_id bmp280_acpi_match[] = {
- {"BMP0280", BMP280_CHIP_ID },
- {"BMP0180", BMP180_CHIP_ID },
- {"BMP0085", BMP180_CHIP_ID },
- { },
-};
-MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match);
-
-static const struct i2c_device_id bmp280_id[] = {
- {"bmp280", BMP280_CHIP_ID },
- {"bmp180", BMP180_CHIP_ID },
- {"bmp085", BMP180_CHIP_ID },
- { },
-};
-MODULE_DEVICE_TABLE(i2c, bmp280_id);
-
-static struct i2c_driver bmp280_driver = {
- .driver = {
- .name = "bmp280",
- .acpi_match_table = ACPI_PTR(bmp280_acpi_match),
- },
- .probe = bmp280_probe,
- .id_table = bmp280_id,
-};
-module_i2c_driver(bmp280_driver);
-
-MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
-MODULE_DESCRIPTION("Driver for Bosch Sensortec BMP180/BMP280 pressure and temperature sensor");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/infiniband/hw/hfi1/twsi.c b/drivers/infiniband/hw/hfi1/twsi.c
deleted file mode 100644
index e82e52a63..000000000
--- a/drivers/infiniband/hw/hfi1/twsi.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-
-#include "hfi.h"
-#include "twsi.h"
-
-/*
- * "Two Wire Serial Interface" support.
- *
- * Originally written for a not-quite-i2c serial eeprom, which is
- * still used on some supported boards. Later boards have added a
- * variety of other uses, most board-specific, so the bit-boffing
- * part has been split off to this file, while the other parts
- * have been moved to chip-specific files.
- *
- * We have also dropped all pretense of fully generic (e.g. pretend
- * we don't know whether '1' is the higher voltage) interface, as
- * the restrictions of the generic i2c interface (e.g. no access from
- * driver itself) make it unsuitable for this use.
- */
-
-#define READ_CMD 1
-#define WRITE_CMD 0
-
-/**
- * i2c_wait_for_writes - wait for a write
- * @dd: the hfi1_ib device
- *
- * We use this instead of udelay directly, so we can make sure
- * that previous register writes have been flushed all the way
- * to the chip. Since we are delaying anyway, the cost doesn't
- * hurt, and makes the bit twiddling more regular
- */
-static void i2c_wait_for_writes(struct hfi1_devdata *dd, u32 target)
-{
- /*
- * implicit read of EXTStatus is as good as explicit
- * read of scratch, if all we want to do is flush
- * writes.
- */
- hfi1_gpio_mod(dd, target, 0, 0, 0);
- rmb(); /* inlined, so prevent compiler reordering */
-}
-
-/*
- * QSFP modules are allowed to hold SCL low for 500uSec. Allow twice that
- * for "almost compliant" modules
- */
-#define SCL_WAIT_USEC 1000
-
-/* BUF_WAIT is time bus must be free between STOP or ACK and to next START.
- * Should be 20, but some chips need more.
- */
-#define TWSI_BUF_WAIT_USEC 60
-
-static void scl_out(struct hfi1_devdata *dd, u32 target, u8 bit)
-{
- u32 mask;
-
- udelay(1);
-
- mask = QSFP_HFI0_I2CCLK;
-
- /* SCL is meant to be bare-drain, so never set "OUT", just DIR */
- hfi1_gpio_mod(dd, target, 0, bit ? 0 : mask, mask);
-
- /*
- * Allow for slow slaves by simple
- * delay for falling edge, sampling on rise.
- */
- if (!bit) {
- udelay(2);
- } else {
- int rise_usec;
-
- for (rise_usec = SCL_WAIT_USEC; rise_usec > 0; rise_usec -= 2) {
- if (mask & hfi1_gpio_mod(dd, target, 0, 0, 0))
- break;
- udelay(2);
- }
- if (rise_usec <= 0)
- dd_dev_err(dd, "SCL interface stuck low > %d uSec\n",
- SCL_WAIT_USEC);
- }
- i2c_wait_for_writes(dd, target);
-}
-
-static u8 scl_in(struct hfi1_devdata *dd, u32 target, int wait)
-{
- u32 read_val, mask;
-
- mask = QSFP_HFI0_I2CCLK;
- /* SCL is meant to be bare-drain, so never set "OUT", just DIR */
- hfi1_gpio_mod(dd, target, 0, 0, mask);
- read_val = hfi1_gpio_mod(dd, target, 0, 0, 0);
- if (wait)
- i2c_wait_for_writes(dd, target);
- return (read_val & mask) >> GPIO_SCL_NUM;
-}
-
-static void sda_out(struct hfi1_devdata *dd, u32 target, u8 bit)
-{
- u32 mask;
-
- mask = QSFP_HFI0_I2CDAT;
-
- /* SDA is meant to be bare-drain, so never set "OUT", just DIR */
- hfi1_gpio_mod(dd, target, 0, bit ? 0 : mask, mask);
-
- i2c_wait_for_writes(dd, target);
- udelay(2);
-}
-
-static u8 sda_in(struct hfi1_devdata *dd, u32 target, int wait)
-{
- u32 read_val, mask;
-
- mask = QSFP_HFI0_I2CDAT;
- /* SDA is meant to be bare-drain, so never set "OUT", just DIR */
- hfi1_gpio_mod(dd, target, 0, 0, mask);
- read_val = hfi1_gpio_mod(dd, target, 0, 0, 0);
- if (wait)
- i2c_wait_for_writes(dd, target);
- return (read_val & mask) >> GPIO_SDA_NUM;
-}
-
-/**
- * i2c_ackrcv - see if ack following write is true
- * @dd: the hfi1_ib device
- */
-static int i2c_ackrcv(struct hfi1_devdata *dd, u32 target)
-{
- u8 ack_received;
-
- /* AT ENTRY SCL = LOW */
- /* change direction, ignore data */
- ack_received = sda_in(dd, target, 1);
- scl_out(dd, target, 1);
- ack_received = sda_in(dd, target, 1) == 0;
- scl_out(dd, target, 0);
- return ack_received;
-}
-
-static void stop_cmd(struct hfi1_devdata *dd, u32 target);
-
-/**
- * rd_byte - read a byte, sending STOP on last, else ACK
- * @dd: the hfi1_ib device
- *
- * Returns byte shifted out of device
- */
-static int rd_byte(struct hfi1_devdata *dd, u32 target, int last)
-{
- int bit_cntr, data;
-
- data = 0;
-
- for (bit_cntr = 7; bit_cntr >= 0; --bit_cntr) {
- data <<= 1;
- scl_out(dd, target, 1);
- data |= sda_in(dd, target, 0);
- scl_out(dd, target, 0);
- }
- if (last) {
- scl_out(dd, target, 1);
- stop_cmd(dd, target);
- } else {
- sda_out(dd, target, 0);
- scl_out(dd, target, 1);
- scl_out(dd, target, 0);
- sda_out(dd, target, 1);
- }
- return data;
-}
-
-/**
- * wr_byte - write a byte, one bit at a time
- * @dd: the hfi1_ib device
- * @data: the byte to write
- *
- * Returns 0 if we got the following ack, otherwise 1
- */
-static int wr_byte(struct hfi1_devdata *dd, u32 target, u8 data)
-{
- int bit_cntr;
- u8 bit;
-
- for (bit_cntr = 7; bit_cntr >= 0; bit_cntr--) {
- bit = (data >> bit_cntr) & 1;
- sda_out(dd, target, bit);
- scl_out(dd, target, 1);
- scl_out(dd, target, 0);
- }
- return (!i2c_ackrcv(dd, target)) ? 1 : 0;
-}
-
-/*
- * issue TWSI start sequence:
- * (both clock/data high, clock high, data low while clock is high)
- */
-static void start_seq(struct hfi1_devdata *dd, u32 target)
-{
- sda_out(dd, target, 1);
- scl_out(dd, target, 1);
- sda_out(dd, target, 0);
- udelay(1);
- scl_out(dd, target, 0);
-}
-
-/**
- * stop_seq - transmit the stop sequence
- * @dd: the hfi1_ib device
- *
- * (both clock/data low, clock high, data high while clock is high)
- */
-static void stop_seq(struct hfi1_devdata *dd, u32 target)
-{
- scl_out(dd, target, 0);
- sda_out(dd, target, 0);
- scl_out(dd, target, 1);
- sda_out(dd, target, 1);
-}
-
-/**
- * stop_cmd - transmit the stop condition
- * @dd: the hfi1_ib device
- *
- * (both clock/data low, clock high, data high while clock is high)
- */
-static void stop_cmd(struct hfi1_devdata *dd, u32 target)
-{
- stop_seq(dd, target);
- udelay(TWSI_BUF_WAIT_USEC);
-}
-
-/**
- * hfi1_twsi_reset - reset I2C communication
- * @dd: the hfi1_ib device
- * returns 0 if ok, -EIO on error
- */
-int hfi1_twsi_reset(struct hfi1_devdata *dd, u32 target)
-{
- int clock_cycles_left = 9;
- u32 mask;
-
- /* Both SCL and SDA should be high. If not, there
- * is something wrong.
- */
- mask = QSFP_HFI0_I2CCLK | QSFP_HFI0_I2CDAT;
-
- /*
- * Force pins to desired innocuous state.
- * This is the default power-on state with out=0 and dir=0,
- * So tri-stated and should be floating high (barring HW problems)
- */
- hfi1_gpio_mod(dd, target, 0, 0, mask);
-
- /* Check if SCL is low, if it is low then we have a slave device
- * misbehaving and there is not much we can do.
- */
- if (!scl_in(dd, target, 0))
- return -EIO;
-
- /* Check if SDA is low, if it is low then we have to clock SDA
- * up to 9 times for the device to release the bus
- */
- while (clock_cycles_left--) {
- if (sda_in(dd, target, 0))
- return 0;
- scl_out(dd, target, 0);
- scl_out(dd, target, 1);
- }
-
- return -EIO;
-}
-
-#define HFI1_TWSI_START 0x100
-#define HFI1_TWSI_STOP 0x200
-
-/* Write byte to TWSI, optionally prefixed with START or suffixed with
- * STOP.
- * returns 0 if OK (ACK received), else != 0
- */
-static int twsi_wr(struct hfi1_devdata *dd, u32 target, int data, int flags)
-{
- int ret = 1;
-
- if (flags & HFI1_TWSI_START)
- start_seq(dd, target);
-
- /* Leaves SCL low (from i2c_ackrcv()) */
- ret = wr_byte(dd, target, data);
-
- if (flags & HFI1_TWSI_STOP)
- stop_cmd(dd, target);
- return ret;
-}
-
-/* Added functionality for IBA7220-based cards */
-#define HFI1_TEMP_DEV 0x98
-
-/*
- * hfi1_twsi_blk_rd
- * General interface for data transfer from twsi devices.
- * One vestige of its former role is that it recognizes a device
- * HFI1_TWSI_NO_DEV and does the correct operation for the legacy part,
- * which responded to all TWSI device codes, interpreting them as
- * address within device. On all other devices found on board handled by
- * this driver, the device is followed by a N-byte "address" which selects
- * the "register" or "offset" within the device from which data should
- * be read.
- */
-int hfi1_twsi_blk_rd(struct hfi1_devdata *dd, u32 target, int dev, int addr,
- void *buffer, int len)
-{
- u8 *bp = buffer;
- int ret = 1;
- int i;
- int offset_size;
-
- /* obtain the offset size, strip it from the device address */
- offset_size = (dev >> 8) & 0xff;
- dev &= 0xff;
-
- /* allow at most a 2 byte offset */
- if (offset_size > 2)
- goto bail;
-
- if (dev == HFI1_TWSI_NO_DEV) {
- /* legacy not-really-I2C */
- addr = (addr << 1) | READ_CMD;
- ret = twsi_wr(dd, target, addr, HFI1_TWSI_START);
- } else {
- /* Actual I2C */
- if (offset_size) {
- ret = twsi_wr(dd, target,
- dev | WRITE_CMD, HFI1_TWSI_START);
- if (ret) {
- stop_cmd(dd, target);
- goto bail;
- }
-
- for (i = 0; i < offset_size; i++) {
- ret = twsi_wr(dd, target,
- (addr >> (i * 8)) & 0xff, 0);
- udelay(TWSI_BUF_WAIT_USEC);
- if (ret) {
- dd_dev_err(dd, "Failed to write byte %d of offset 0x%04X\n",
- i, addr);
- goto bail;
- }
- }
- }
- ret = twsi_wr(dd, target, dev | READ_CMD, HFI1_TWSI_START);
- }
- if (ret) {
- stop_cmd(dd, target);
- goto bail;
- }
-
- /*
- * block devices keeps clocking data out as long as we ack,
- * automatically incrementing the address. Some have "pages"
- * whose boundaries will not be crossed, but the handling
- * of these is left to the caller, who is in a better
- * position to know.
- */
- while (len-- > 0) {
- /*
- * Get and store data, sending ACK if length remaining,
- * else STOP
- */
- *bp++ = rd_byte(dd, target, !len);
- }
-
- ret = 0;
-
-bail:
- return ret;
-}
-
-/*
- * hfi1_twsi_blk_wr
- * General interface for data transfer to twsi devices.
- * One vestige of its former role is that it recognizes a device
- * HFI1_TWSI_NO_DEV and does the correct operation for the legacy part,
- * which responded to all TWSI device codes, interpreting them as
- * address within device. On all other devices found on board handled by
- * this driver, the device is followed by a N-byte "address" which selects
- * the "register" or "offset" within the device to which data should
- * be written.
- */
-int hfi1_twsi_blk_wr(struct hfi1_devdata *dd, u32 target, int dev, int addr,
- const void *buffer, int len)
-{
- const u8 *bp = buffer;
- int ret = 1;
- int i;
- int offset_size;
-
- /* obtain the offset size, strip it from the device address */
- offset_size = (dev >> 8) & 0xff;
- dev &= 0xff;
-
- /* allow at most a 2 byte offset */
- if (offset_size > 2)
- goto bail;
-
- if (dev == HFI1_TWSI_NO_DEV) {
- if (twsi_wr(dd, target, (addr << 1) | WRITE_CMD,
- HFI1_TWSI_START)) {
- goto failed_write;
- }
- } else {
- /* Real I2C */
- if (twsi_wr(dd, target, dev | WRITE_CMD, HFI1_TWSI_START))
- goto failed_write;
- }
-
- for (i = 0; i < offset_size; i++) {
- ret = twsi_wr(dd, target, (addr >> (i * 8)) & 0xff, 0);
- udelay(TWSI_BUF_WAIT_USEC);
- if (ret) {
- dd_dev_err(dd, "Failed to write byte %d of offset 0x%04X\n",
- i, addr);
- goto bail;
- }
- }
-
- for (i = 0; i < len; i++)
- if (twsi_wr(dd, target, *bp++, 0))
- goto failed_write;
-
- ret = 0;
-
-failed_write:
- stop_cmd(dd, target);
-
-bail:
- return ret;
-}
diff --git a/drivers/infiniband/hw/hfi1/twsi.h b/drivers/infiniband/hw/hfi1/twsi.h
deleted file mode 100644
index 5b8a5b5e7..000000000
--- a/drivers/infiniband/hw/hfi1/twsi.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _TWSI_H
-#define _TWSI_H
-/*
- * Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#define HFI1_TWSI_NO_DEV 0xFF
-
-struct hfi1_devdata;
-
-/* Bit position of SDA/SCL pins in ASIC_QSFP* registers */
-#define GPIO_SDA_NUM 1
-#define GPIO_SCL_NUM 0
-
-/* these functions must be called with qsfp_lock held */
-int hfi1_twsi_reset(struct hfi1_devdata *dd, u32 target);
-int hfi1_twsi_blk_rd(struct hfi1_devdata *dd, u32 target, int dev, int addr,
- void *buffer, int len);
-int hfi1_twsi_blk_wr(struct hfi1_devdata *dd, u32 target, int dev, int addr,
- const void *buffer, int len);
-
-#endif /* _TWSI_H */
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
deleted file mode 100644
index 4b09e815a..000000000
--- a/drivers/iommu/msm_iommu_dev.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/iommu.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include "msm_iommu_hw-8xxx.h"
-#include "msm_iommu.h"
-
-struct iommu_ctx_iter_data {
- /* input */
- const char *name;
-
- /* output */
- struct device *dev;
-};
-
-static struct platform_device *msm_iommu_root_dev;
-
-static int each_iommu_ctx(struct device *dev, void *data)
-{
- struct iommu_ctx_iter_data *res = data;
- struct msm_iommu_ctx_dev *c = dev->platform_data;
-
- if (!res || !c || !c->name || !res->name)
- return -EINVAL;
-
- if (!strcmp(res->name, c->name)) {
- res->dev = dev;
- return 1;
- }
- return 0;
-}
-
-static int each_iommu(struct device *dev, void *data)
-{
- return device_for_each_child(dev, data, each_iommu_ctx);
-}
-
-struct device *msm_iommu_get_ctx(const char *ctx_name)
-{
- struct iommu_ctx_iter_data r;
- int found;
-
- if (!msm_iommu_root_dev) {
- pr_err("No root IOMMU device.\n");
- goto fail;
- }
-
- r.name = ctx_name;
- found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
-
- if (!found) {
- pr_err("Could not find context <%s>\n", ctx_name);
- goto fail;
- }
-
- return r.dev;
-fail:
- return NULL;
-}
-EXPORT_SYMBOL(msm_iommu_get_ctx);
-
-static void msm_iommu_reset(void __iomem *base, int ncb)
-{
- int ctx;
-
- SET_RPUE(base, 0);
- SET_RPUEIE(base, 0);
- SET_ESRRESTORE(base, 0);
- SET_TBE(base, 0);
- SET_CR(base, 0);
- SET_SPDMBE(base, 0);
- SET_TESTBUSCR(base, 0);
- SET_TLBRSW(base, 0);
- SET_GLOBAL_TLBIALL(base, 0);
- SET_RPU_ACR(base, 0);
- SET_TLBLKCRWE(base, 1);
-
- for (ctx = 0; ctx < ncb; ctx++) {
- SET_BPRCOSH(base, ctx, 0);
- SET_BPRCISH(base, ctx, 0);
- SET_BPRCNSH(base, ctx, 0);
- SET_BPSHCFG(base, ctx, 0);
- SET_BPMTCFG(base, ctx, 0);
- SET_ACTLR(base, ctx, 0);
- SET_SCTLR(base, ctx, 0);
- SET_FSRRESTORE(base, ctx, 0);
- SET_TTBR0(base, ctx, 0);
- SET_TTBR1(base, ctx, 0);
- SET_TTBCR(base, ctx, 0);
- SET_BFBCR(base, ctx, 0);
- SET_PAR(base, ctx, 0);
- SET_FAR(base, ctx, 0);
- SET_CTX_TLBIALL(base, ctx, 0);
- SET_TLBFLPTER(base, ctx, 0);
- SET_TLBSLPTER(base, ctx, 0);
- SET_TLBLKCR(base, ctx, 0);
- SET_PRRR(base, ctx, 0);
- SET_NMRR(base, ctx, 0);
- SET_CONTEXTIDR(base, ctx, 0);
- }
-}
-
-static int msm_iommu_probe(struct platform_device *pdev)
-{
- struct resource *r;
- struct clk *iommu_clk;
- struct clk *iommu_pclk;
- struct msm_iommu_drvdata *drvdata;
- struct msm_iommu_dev *iommu_dev = dev_get_platdata(&pdev->dev);
- void __iomem *regs_base;
- int ret, irq, par;
-
- if (pdev->id == -1) {
- msm_iommu_root_dev = pdev;
- return 0;
- }
-
- drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-
- if (!drvdata) {
- ret = -ENOMEM;
- goto fail;
- }
-
- if (!iommu_dev) {
- ret = -ENODEV;
- goto fail;
- }
-
- iommu_pclk = clk_get(NULL, "smmu_pclk");
- if (IS_ERR(iommu_pclk)) {
- ret = -ENODEV;
- goto fail;
- }
-
- ret = clk_prepare_enable(iommu_pclk);
- if (ret)
- goto fail_enable;
-
- iommu_clk = clk_get(&pdev->dev, "iommu_clk");
-
- if (!IS_ERR(iommu_clk)) {
- if (clk_get_rate(iommu_clk) == 0)
- clk_set_rate(iommu_clk, 1);
-
- ret = clk_prepare_enable(iommu_clk);
- if (ret) {
- clk_put(iommu_clk);
- goto fail_pclk;
- }
- } else
- iommu_clk = NULL;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
- regs_base = devm_ioremap_resource(&pdev->dev, r);
- if (IS_ERR(regs_base)) {
- ret = PTR_ERR(regs_base);
- goto fail_clk;
- }
-
- irq = platform_get_irq_byname(pdev, "secure_irq");
- if (irq < 0) {
- ret = -ENODEV;
- goto fail_clk;
- }
-
- msm_iommu_reset(regs_base, iommu_dev->ncb);
-
- SET_M(regs_base, 0, 1);
- SET_PAR(regs_base, 0, 0);
- SET_V2PCFG(regs_base, 0, 1);
- SET_V2PPR(regs_base, 0, 0);
- par = GET_PAR(regs_base, 0);
- SET_V2PCFG(regs_base, 0, 0);
- SET_M(regs_base, 0, 0);
-
- if (!par) {
- pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
- ret = -ENODEV;
- goto fail_clk;
- }
-
- ret = request_irq(irq, msm_iommu_fault_handler, 0,
- "msm_iommu_secure_irpt_handler", drvdata);
- if (ret) {
- pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
- goto fail_clk;
- }
-
-
- drvdata->pclk = iommu_pclk;
- drvdata->clk = iommu_clk;
- drvdata->base = regs_base;
- drvdata->irq = irq;
- drvdata->ncb = iommu_dev->ncb;
-
- pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
- iommu_dev->name, regs_base, irq, iommu_dev->ncb);
-
- platform_set_drvdata(pdev, drvdata);
-
- clk_disable(iommu_clk);
-
- clk_disable(iommu_pclk);
-
- return 0;
-fail_clk:
- if (iommu_clk) {
- clk_disable(iommu_clk);
- clk_put(iommu_clk);
- }
-fail_pclk:
- clk_disable_unprepare(iommu_pclk);
-fail_enable:
- clk_put(iommu_pclk);
-fail:
- kfree(drvdata);
- return ret;
-}
-
-static int msm_iommu_remove(struct platform_device *pdev)
-{
- struct msm_iommu_drvdata *drv = NULL;
-
- drv = platform_get_drvdata(pdev);
- if (drv) {
- if (drv->clk) {
- clk_unprepare(drv->clk);
- clk_put(drv->clk);
- }
- clk_unprepare(drv->pclk);
- clk_put(drv->pclk);
- memset(drv, 0, sizeof(*drv));
- kfree(drv);
- }
- return 0;
-}
-
-static int msm_iommu_ctx_probe(struct platform_device *pdev)
-{
- struct msm_iommu_ctx_dev *c = dev_get_platdata(&pdev->dev);
- struct msm_iommu_drvdata *drvdata;
- struct msm_iommu_ctx_drvdata *ctx_drvdata;
- int i, ret;
-
- if (!c || !pdev->dev.parent)
- return -EINVAL;
-
- drvdata = dev_get_drvdata(pdev->dev.parent);
- if (!drvdata)
- return -ENODEV;
-
- ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
- if (!ctx_drvdata)
- return -ENOMEM;
-
- ctx_drvdata->num = c->num;
- ctx_drvdata->pdev = pdev;
-
- INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
- platform_set_drvdata(pdev, ctx_drvdata);
-
- ret = clk_prepare_enable(drvdata->pclk);
- if (ret)
- goto fail;
-
- if (drvdata->clk) {
- ret = clk_prepare_enable(drvdata->clk);
- if (ret) {
- clk_disable_unprepare(drvdata->pclk);
- goto fail;
- }
- }
-
- /* Program the M2V tables for this context */
- for (i = 0; i < MAX_NUM_MIDS; i++) {
- int mid = c->mids[i];
- if (mid == -1)
- break;
-
- SET_M2VCBR_N(drvdata->base, mid, 0);
- SET_CBACR_N(drvdata->base, c->num, 0);
-
- /* Set VMID = 0 */
- SET_VMID(drvdata->base, mid, 0);
-
- /* Set the context number for that MID to this context */
- SET_CBNDX(drvdata->base, mid, c->num);
-
- /* Set MID associated with this context bank to 0*/
- SET_CBVMID(drvdata->base, c->num, 0);
-
- /* Set the ASID for TLB tagging for this context */
- SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);
-
- /* Set security bit override to be Non-secure */
- SET_NSCFG(drvdata->base, mid, 3);
- }
-
- clk_disable(drvdata->clk);
- clk_disable(drvdata->pclk);
-
- dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
- return 0;
-fail:
- kfree(ctx_drvdata);
- return ret;
-}
-
-static int msm_iommu_ctx_remove(struct platform_device *pdev)
-{
- struct msm_iommu_ctx_drvdata *drv = NULL;
- drv = platform_get_drvdata(pdev);
- if (drv) {
- memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
- kfree(drv);
- }
- return 0;
-}
-
-static struct platform_driver msm_iommu_driver = {
- .driver = {
- .name = "msm_iommu",
- },
- .probe = msm_iommu_probe,
- .remove = msm_iommu_remove,
-};
-
-static struct platform_driver msm_iommu_ctx_driver = {
- .driver = {
- .name = "msm_iommu_ctx",
- },
- .probe = msm_iommu_ctx_probe,
- .remove = msm_iommu_ctx_remove,
-};
-
-static struct platform_driver * const drivers[] = {
- &msm_iommu_driver,
- &msm_iommu_ctx_driver,
-};
-
-static int __init msm_iommu_driver_init(void)
-{
- return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
-}
-
-static void __exit msm_iommu_driver_exit(void)
-{
- platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
-}
-
-subsys_initcall(msm_iommu_driver_init);
-module_exit(msm_iommu_driver_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/drivers/leds/trigger/ledtrig-ide-disk.c b/drivers/leds/trigger/ledtrig-ide-disk.c
deleted file mode 100644
index 15123d389..000000000
--- a/drivers/leds/trigger/ledtrig-ide-disk.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * LED IDE-Disk Activity Trigger
- *
- * Copyright 2006 Openedhand Ltd.
- *
- * Author: Richard Purdie <rpurdie@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/leds.h>
-
-#define BLINK_DELAY 30
-
-DEFINE_LED_TRIGGER(ledtrig_ide);
-
-void ledtrig_ide_activity(void)
-{
- unsigned long ide_blink_delay = BLINK_DELAY;
-
- led_trigger_blink_oneshot(ledtrig_ide,
- &ide_blink_delay, &ide_blink_delay, 0);
-}
-EXPORT_SYMBOL(ledtrig_ide_activity);
-
-static int __init ledtrig_ide_init(void)
-{
- led_trigger_register_simple("ide-disk", &ledtrig_ide);
- return 0;
-}
-device_initcall(ledtrig_ide_init);
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
deleted file mode 100644
index 7f90ce5a5..000000000
--- a/drivers/misc/bh1780gli.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * bh1780gli.c
- * ROHM Ambient Light Sensor Driver
- *
- * Copyright (C) 2010 Texas Instruments
- * Author: Hemanth V <hemanthv@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/of.h>
-
-#define BH1780_REG_CONTROL 0x80
-#define BH1780_REG_PARTID 0x8A
-#define BH1780_REG_MANFID 0x8B
-#define BH1780_REG_DLOW 0x8C
-#define BH1780_REG_DHIGH 0x8D
-
-#define BH1780_REVMASK (0xf)
-#define BH1780_POWMASK (0x3)
-#define BH1780_POFF (0x0)
-#define BH1780_PON (0x3)
-
-/* power on settling time in ms */
-#define BH1780_PON_DELAY 2
-
-struct bh1780_data {
- struct i2c_client *client;
- int power_state;
- /* lock for sysfs operations */
- struct mutex lock;
-};
-
-static int bh1780_write(struct bh1780_data *ddata, u8 reg, u8 val, char *msg)
-{
- int ret = i2c_smbus_write_byte_data(ddata->client, reg, val);
- if (ret < 0)
- dev_err(&ddata->client->dev,
- "i2c_smbus_write_byte_data failed error %d Register (%s)\n",
- ret, msg);
- return ret;
-}
-
-static int bh1780_read(struct bh1780_data *ddata, u8 reg, char *msg)
-{
- int ret = i2c_smbus_read_byte_data(ddata->client, reg);
- if (ret < 0)
- dev_err(&ddata->client->dev,
- "i2c_smbus_read_byte_data failed error %d Register (%s)\n",
- ret, msg);
- return ret;
-}
-
-static ssize_t bh1780_show_lux(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct bh1780_data *ddata = platform_get_drvdata(pdev);
- int lsb, msb;
-
- lsb = bh1780_read(ddata, BH1780_REG_DLOW, "DLOW");
- if (lsb < 0)
- return lsb;
-
- msb = bh1780_read(ddata, BH1780_REG_DHIGH, "DHIGH");
- if (msb < 0)
- return msb;
-
- return sprintf(buf, "%d\n", (msb << 8) | lsb);
-}
-
-static ssize_t bh1780_show_power_state(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct bh1780_data *ddata = platform_get_drvdata(pdev);
- int state;
-
- state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL");
- if (state < 0)
- return state;
-
- return sprintf(buf, "%d\n", state & BH1780_POWMASK);
-}
-
-static ssize_t bh1780_store_power_state(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct bh1780_data *ddata = platform_get_drvdata(pdev);
- unsigned long val;
- int error;
-
- error = kstrtoul(buf, 0, &val);
- if (error)
- return error;
-
- if (val < BH1780_POFF || val > BH1780_PON)
- return -EINVAL;
-
- mutex_lock(&ddata->lock);
-
- error = bh1780_write(ddata, BH1780_REG_CONTROL, val, "CONTROL");
- if (error < 0) {
- mutex_unlock(&ddata->lock);
- return error;
- }
-
- msleep(BH1780_PON_DELAY);
- ddata->power_state = val;
- mutex_unlock(&ddata->lock);
-
- return count;
-}
-
-static DEVICE_ATTR(lux, S_IRUGO, bh1780_show_lux, NULL);
-
-static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
- bh1780_show_power_state, bh1780_store_power_state);
-
-static struct attribute *bh1780_attributes[] = {
- &dev_attr_power_state.attr,
- &dev_attr_lux.attr,
- NULL
-};
-
-static const struct attribute_group bh1780_attr_group = {
- .attrs = bh1780_attributes,
-};
-
-static int bh1780_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- int ret;
- struct bh1780_data *ddata;
- struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
- return -EIO;
-
- ddata = devm_kzalloc(&client->dev, sizeof(struct bh1780_data),
- GFP_KERNEL);
- if (ddata == NULL)
- return -ENOMEM;
-
- ddata->client = client;
- i2c_set_clientdata(client, ddata);
-
- ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID");
- if (ret < 0)
- return ret;
-
- dev_info(&client->dev, "Ambient Light Sensor, Rev : %d\n",
- (ret & BH1780_REVMASK));
-
- mutex_init(&ddata->lock);
-
- return sysfs_create_group(&client->dev.kobj, &bh1780_attr_group);
-}
-
-static int bh1780_remove(struct i2c_client *client)
-{
- sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int bh1780_suspend(struct device *dev)
-{
- struct bh1780_data *ddata;
- int state, ret;
- struct i2c_client *client = to_i2c_client(dev);
-
- ddata = i2c_get_clientdata(client);
- state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL");
- if (state < 0)
- return state;
-
- ddata->power_state = state & BH1780_POWMASK;
-
- ret = bh1780_write(ddata, BH1780_REG_CONTROL, BH1780_POFF,
- "CONTROL");
-
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int bh1780_resume(struct device *dev)
-{
- struct bh1780_data *ddata;
- int state, ret;
- struct i2c_client *client = to_i2c_client(dev);
-
- ddata = i2c_get_clientdata(client);
- state = ddata->power_state;
- ret = bh1780_write(ddata, BH1780_REG_CONTROL, state,
- "CONTROL");
-
- if (ret < 0)
- return ret;
-
- return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
-static SIMPLE_DEV_PM_OPS(bh1780_pm, bh1780_suspend, bh1780_resume);
-
-static const struct i2c_device_id bh1780_id[] = {
- { "bh1780", 0 },
- { },
-};
-
-MODULE_DEVICE_TABLE(i2c, bh1780_id);
-
-#ifdef CONFIG_OF
-static const struct of_device_id of_bh1780_match[] = {
- { .compatible = "rohm,bh1780gli", },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, of_bh1780_match);
-#endif
-
-static struct i2c_driver bh1780_driver = {
- .probe = bh1780_probe,
- .remove = bh1780_remove,
- .id_table = bh1780_id,
- .driver = {
- .name = "bh1780",
- .pm = &bh1780_pm,
- .of_match_table = of_match_ptr(of_bh1780_match),
- },
-};
-
-module_i2c_driver(bh1780_driver);
-
-MODULE_DESCRIPTION("BH1780GLI Ambient Light Sensor Driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
deleted file mode 100644
index 0a5cbbe12..000000000
--- a/drivers/misc/lkdtm.c
+++ /dev/null
@@ -1,1023 +0,0 @@
-/*
- * Kprobe module for testing crash dumps
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) IBM Corporation, 2006
- *
- * Author: Ankita Garg <ankita@in.ibm.com>
- *
- * This module induces system failures at predefined crashpoints to
- * evaluate the reliability of crash dumps obtained using different dumping
- * solutions.
- *
- * It is adapted from the Linux Kernel Dump Test Tool by
- * Fernando Luis Vazquez Cao <http://lkdtt.sourceforge.net>
- *
- * Debugfs support added by Simon Kagstrom <simon.kagstrom@netinsight.net>
- *
- * See Documentation/fault-injection/provoke-crashes.txt for instructions
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/buffer_head.h>
-#include <linux/kprobes.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
-#include <linux/slab.h>
-#include <scsi/scsi_cmnd.h>
-#include <linux/debugfs.h>
-#include <linux/vmalloc.h>
-#include <linux/mman.h>
-#include <asm/cacheflush.h>
-
-#ifdef CONFIG_IDE
-#include <linux/ide.h>
-#endif
-
-/*
- * Make sure our attempts to over run the kernel stack doesn't trigger
- * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
- * recurse past the end of THREAD_SIZE by default.
- */
-#if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN > 0)
-#define REC_STACK_SIZE (CONFIG_FRAME_WARN / 2)
-#else
-#define REC_STACK_SIZE (THREAD_SIZE / 8)
-#endif
-#define REC_NUM_DEFAULT ((THREAD_SIZE / REC_STACK_SIZE) * 2)
-
-#define DEFAULT_COUNT 10
-#define EXEC_SIZE 64
-
-enum cname {
- CN_INVALID,
- CN_INT_HARDWARE_ENTRY,
- CN_INT_HW_IRQ_EN,
- CN_INT_TASKLET_ENTRY,
- CN_FS_DEVRW,
- CN_MEM_SWAPOUT,
- CN_TIMERADD,
- CN_SCSI_DISPATCH_CMD,
- CN_IDE_CORE_CP,
- CN_DIRECT,
-};
-
-enum ctype {
- CT_NONE,
- CT_PANIC,
- CT_BUG,
- CT_WARNING,
- CT_EXCEPTION,
- CT_LOOP,
- CT_OVERFLOW,
- CT_CORRUPT_STACK,
- CT_UNALIGNED_LOAD_STORE_WRITE,
- CT_OVERWRITE_ALLOCATION,
- CT_WRITE_AFTER_FREE,
- CT_READ_AFTER_FREE,
- CT_WRITE_BUDDY_AFTER_FREE,
- CT_READ_BUDDY_AFTER_FREE,
- CT_SOFTLOCKUP,
- CT_HARDLOCKUP,
- CT_SPINLOCKUP,
- CT_HUNG_TASK,
- CT_EXEC_DATA,
- CT_EXEC_STACK,
- CT_EXEC_KMALLOC,
- CT_EXEC_VMALLOC,
- CT_EXEC_USERSPACE,
- CT_ACCESS_USERSPACE,
- CT_WRITE_RO,
- CT_WRITE_RO_AFTER_INIT,
- CT_WRITE_KERN,
- CT_WRAP_ATOMIC
-};
-
-static char* cp_name[] = {
- "INT_HARDWARE_ENTRY",
- "INT_HW_IRQ_EN",
- "INT_TASKLET_ENTRY",
- "FS_DEVRW",
- "MEM_SWAPOUT",
- "TIMERADD",
- "SCSI_DISPATCH_CMD",
- "IDE_CORE_CP",
- "DIRECT",
-};
-
-static char* cp_type[] = {
- "PANIC",
- "BUG",
- "WARNING",
- "EXCEPTION",
- "LOOP",
- "OVERFLOW",
- "CORRUPT_STACK",
- "UNALIGNED_LOAD_STORE_WRITE",
- "OVERWRITE_ALLOCATION",
- "WRITE_AFTER_FREE",
- "READ_AFTER_FREE",
- "WRITE_BUDDY_AFTER_FREE",
- "READ_BUDDY_AFTER_FREE",
- "SOFTLOCKUP",
- "HARDLOCKUP",
- "SPINLOCKUP",
- "HUNG_TASK",
- "EXEC_DATA",
- "EXEC_STACK",
- "EXEC_KMALLOC",
- "EXEC_VMALLOC",
- "EXEC_USERSPACE",
- "ACCESS_USERSPACE",
- "WRITE_RO",
- "WRITE_RO_AFTER_INIT",
- "WRITE_KERN",
- "WRAP_ATOMIC"
-};
-
-static struct jprobe lkdtm;
-
-static int lkdtm_parse_commandline(void);
-static void lkdtm_handler(void);
-
-static char* cpoint_name;
-static char* cpoint_type;
-static int cpoint_count = DEFAULT_COUNT;
-static int recur_count = REC_NUM_DEFAULT;
-
-static enum cname cpoint = CN_INVALID;
-static enum ctype cptype = CT_NONE;
-static int count = DEFAULT_COUNT;
-static DEFINE_SPINLOCK(count_lock);
-static DEFINE_SPINLOCK(lock_me_up);
-
-static u8 data_area[EXEC_SIZE];
-
-static const unsigned long rodata = 0xAA55AA55;
-static unsigned long ro_after_init __ro_after_init = 0x55AA5500;
-
-module_param(recur_count, int, 0644);
-MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test");
-module_param(cpoint_name, charp, 0444);
-MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed");
-module_param(cpoint_type, charp, 0444);
-MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\
- "hitting the crash point");
-module_param(cpoint_count, int, 0644);
-MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\
- "crash point is to be hit to trigger action");
-
-static unsigned int jp_do_irq(unsigned int irq)
-{
- lkdtm_handler();
- jprobe_return();
- return 0;
-}
-
-static irqreturn_t jp_handle_irq_event(unsigned int irq,
- struct irqaction *action)
-{
- lkdtm_handler();
- jprobe_return();
- return 0;
-}
-
-static void jp_tasklet_action(struct softirq_action *a)
-{
- lkdtm_handler();
- jprobe_return();
-}
-
-static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
-{
- lkdtm_handler();
- jprobe_return();
-}
-
-struct scan_control;
-
-static unsigned long jp_shrink_inactive_list(unsigned long max_scan,
- struct zone *zone,
- struct scan_control *sc)
-{
- lkdtm_handler();
- jprobe_return();
- return 0;
-}
-
-static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim,
- const enum hrtimer_mode mode)
-{
- lkdtm_handler();
- jprobe_return();
- return 0;
-}
-
-static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd)
-{
- lkdtm_handler();
- jprobe_return();
- return 0;
-}
-
-#ifdef CONFIG_IDE
-static int jp_generic_ide_ioctl(ide_drive_t *drive, struct file *file,
- struct block_device *bdev, unsigned int cmd,
- unsigned long arg)
-{
- lkdtm_handler();
- jprobe_return();
- return 0;
-}
-#endif
-
-/* Return the crashpoint number or NONE if the name is invalid */
-static enum ctype parse_cp_type(const char *what, size_t count)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(cp_type); i++) {
- if (!strcmp(what, cp_type[i]))
- return i + 1;
- }
-
- return CT_NONE;
-}
-
-static const char *cp_type_to_str(enum ctype type)
-{
- if (type == CT_NONE || type < 0 || type > ARRAY_SIZE(cp_type))
- return "None";
-
- return cp_type[type - 1];
-}
-
-static const char *cp_name_to_str(enum cname name)
-{
- if (name == CN_INVALID || name < 0 || name > ARRAY_SIZE(cp_name))
- return "INVALID";
-
- return cp_name[name - 1];
-}
-
-
-static int lkdtm_parse_commandline(void)
-{
- int i;
- unsigned long flags;
-
- if (cpoint_count < 1 || recur_count < 1)
- return -EINVAL;
-
- spin_lock_irqsave(&count_lock, flags);
- count = cpoint_count;
- spin_unlock_irqrestore(&count_lock, flags);
-
- /* No special parameters */
- if (!cpoint_type && !cpoint_name)
- return 0;
-
- /* Neither or both of these need to be set */
- if (!cpoint_type || !cpoint_name)
- return -EINVAL;
-
- cptype = parse_cp_type(cpoint_type, strlen(cpoint_type));
- if (cptype == CT_NONE)
- return -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(cp_name); i++) {
- if (!strcmp(cpoint_name, cp_name[i])) {
- cpoint = i + 1;
- return 0;
- }
- }
-
- /* Could not find a valid crash point */
- return -EINVAL;
-}
-
-static int recursive_loop(int remaining)
-{
- char buf[REC_STACK_SIZE];
-
- /* Make sure compiler does not optimize this away. */
- memset(buf, (remaining & 0xff) | 0x1, REC_STACK_SIZE);
- if (!remaining)
- return 0;
- else
- return recursive_loop(remaining - 1);
-}
-
-static void do_nothing(void)
-{
- return;
-}
-
-/* Must immediately follow do_nothing for size calculuations to work out. */
-static void do_overwritten(void)
-{
- pr_info("do_overwritten wasn't overwritten!\n");
- return;
-}
-
-static noinline void corrupt_stack(void)
-{
- /* Use default char array length that triggers stack protection. */
- char data[8];
-
- memset((void *)data, 0, 64);
-}
-
-static void noinline execute_location(void *dst)
-{
- void (*func)(void) = dst;
-
- pr_info("attempting ok execution at %p\n", do_nothing);
- do_nothing();
-
- memcpy(dst, do_nothing, EXEC_SIZE);
- flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE);
- pr_info("attempting bad execution at %p\n", func);
- func();
-}
-
-static void execute_user_location(void *dst)
-{
- /* Intentionally crossing kernel/user memory boundary. */
- void (*func)(void) = dst;
-
- pr_info("attempting ok execution at %p\n", do_nothing);
- do_nothing();
-
- if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE))
- return;
- flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE);
- pr_info("attempting bad execution at %p\n", func);
- func();
-}
-
-static void lkdtm_do_action(enum ctype which)
-{
- switch (which) {
- case CT_PANIC:
- panic("dumptest");
- break;
- case CT_BUG:
- BUG();
- break;
- case CT_WARNING:
- WARN_ON(1);
- break;
- case CT_EXCEPTION:
- *((int *) 0) = 0;
- break;
- case CT_LOOP:
- for (;;)
- ;
- break;
- case CT_OVERFLOW:
- (void) recursive_loop(recur_count);
- break;
- case CT_CORRUPT_STACK:
- corrupt_stack();
- break;
- case CT_UNALIGNED_LOAD_STORE_WRITE: {
- static u8 data[5] __attribute__((aligned(4))) = {1, 2,
- 3, 4, 5};
- u32 *p;
- u32 val = 0x12345678;
-
- p = (u32 *)(data + 1);
- if (*p == 0)
- val = 0x87654321;
- *p = val;
- break;
- }
- case CT_OVERWRITE_ALLOCATION: {
- size_t len = 1020;
- u32 *data = kmalloc(len, GFP_KERNEL);
-
- data[1024 / sizeof(u32)] = 0x12345678;
- kfree(data);
- break;
- }
- case CT_WRITE_AFTER_FREE: {
- int *base, *again;
- size_t len = 1024;
- /*
- * The slub allocator uses the first word to store the free
- * pointer in some configurations. Use the middle of the
- * allocation to avoid running into the freelist
- */
- size_t offset = (len / sizeof(*base)) / 2;
-
- base = kmalloc(len, GFP_KERNEL);
- pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]);
- pr_info("Attempting bad write to freed memory at %p\n",
- &base[offset]);
- kfree(base);
- base[offset] = 0x0abcdef0;
- /* Attempt to notice the overwrite. */
- again = kmalloc(len, GFP_KERNEL);
- kfree(again);
- if (again != base)
- pr_info("Hmm, didn't get the same memory range.\n");
-
- break;
- }
- case CT_READ_AFTER_FREE: {
- int *base, *val, saw;
- size_t len = 1024;
- /*
- * The slub allocator uses the first word to store the free
- * pointer in some configurations. Use the middle of the
- * allocation to avoid running into the freelist
- */
- size_t offset = (len / sizeof(*base)) / 2;
-
- base = kmalloc(len, GFP_KERNEL);
- if (!base)
- break;
-
- val = kmalloc(len, GFP_KERNEL);
- if (!val) {
- kfree(base);
- break;
- }
-
- *val = 0x12345678;
- base[offset] = *val;
- pr_info("Value in memory before free: %x\n", base[offset]);
-
- kfree(base);
-
- pr_info("Attempting bad read from freed memory\n");
- saw = base[offset];
- if (saw != *val) {
- /* Good! Poisoning happened, so declare a win. */
- pr_info("Memory correctly poisoned (%x)\n", saw);
- BUG();
- }
- pr_info("Memory was not poisoned\n");
-
- kfree(val);
- break;
- }
- case CT_WRITE_BUDDY_AFTER_FREE: {
- unsigned long p = __get_free_page(GFP_KERNEL);
- if (!p)
- break;
- pr_info("Writing to the buddy page before free\n");
- memset((void *)p, 0x3, PAGE_SIZE);
- free_page(p);
- schedule();
- pr_info("Attempting bad write to the buddy page after free\n");
- memset((void *)p, 0x78, PAGE_SIZE);
- /* Attempt to notice the overwrite. */
- p = __get_free_page(GFP_KERNEL);
- free_page(p);
- schedule();
-
- break;
- }
- case CT_READ_BUDDY_AFTER_FREE: {
- unsigned long p = __get_free_page(GFP_KERNEL);
- int saw, *val;
- int *base;
-
- if (!p)
- break;
-
- val = kmalloc(1024, GFP_KERNEL);
- if (!val) {
- free_page(p);
- break;
- }
-
- base = (int *)p;
-
- *val = 0x12345678;
- base[0] = *val;
- pr_info("Value in memory before free: %x\n", base[0]);
- free_page(p);
- pr_info("Attempting to read from freed memory\n");
- saw = base[0];
- if (saw != *val) {
- /* Good! Poisoning happened, so declare a win. */
- pr_info("Memory correctly poisoned (%x)\n", saw);
- BUG();
- }
- pr_info("Buddy page was not poisoned\n");
-
- kfree(val);
- break;
- }
- case CT_SOFTLOCKUP:
- preempt_disable();
- for (;;)
- cpu_relax();
- break;
- case CT_HARDLOCKUP:
- local_irq_disable();
- for (;;)
- cpu_relax();
- break;
- case CT_SPINLOCKUP:
- /* Must be called twice to trigger. */
- spin_lock(&lock_me_up);
- /* Let sparse know we intended to exit holding the lock. */
- __release(&lock_me_up);
- break;
- case CT_HUNG_TASK:
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule();
- break;
- case CT_EXEC_DATA:
- execute_location(data_area);
- break;
- case CT_EXEC_STACK: {
- u8 stack_area[EXEC_SIZE];
- execute_location(stack_area);
- break;
- }
- case CT_EXEC_KMALLOC: {
- u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL);
- execute_location(kmalloc_area);
- kfree(kmalloc_area);
- break;
- }
- case CT_EXEC_VMALLOC: {
- u32 *vmalloc_area = vmalloc(EXEC_SIZE);
- execute_location(vmalloc_area);
- vfree(vmalloc_area);
- break;
- }
- case CT_EXEC_USERSPACE: {
- unsigned long user_addr;
-
- user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_ANONYMOUS | MAP_PRIVATE, 0);
- if (user_addr >= TASK_SIZE) {
- pr_warn("Failed to allocate user memory\n");
- return;
- }
- execute_user_location((void *)user_addr);
- vm_munmap(user_addr, PAGE_SIZE);
- break;
- }
- case CT_ACCESS_USERSPACE: {
- unsigned long user_addr, tmp = 0;
- unsigned long *ptr;
-
- user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_ANONYMOUS | MAP_PRIVATE, 0);
- if (user_addr >= TASK_SIZE) {
- pr_warn("Failed to allocate user memory\n");
- return;
- }
-
- if (copy_to_user((void __user *)user_addr, &tmp, sizeof(tmp))) {
- pr_warn("copy_to_user failed\n");
- vm_munmap(user_addr, PAGE_SIZE);
- return;
- }
-
- ptr = (unsigned long *)user_addr;
-
- pr_info("attempting bad read at %p\n", ptr);
- tmp = *ptr;
- tmp += 0xc0dec0de;
-
- pr_info("attempting bad write at %p\n", ptr);
- *ptr = tmp;
-
- vm_munmap(user_addr, PAGE_SIZE);
-
- break;
- }
- case CT_WRITE_RO: {
- /* Explicitly cast away "const" for the test. */
- unsigned long *ptr = (unsigned long *)&rodata;
-
- pr_info("attempting bad rodata write at %p\n", ptr);
- *ptr ^= 0xabcd1234;
-
- break;
- }
- case CT_WRITE_RO_AFTER_INIT: {
- unsigned long *ptr = &ro_after_init;
-
- /*
- * Verify we were written to during init. Since an Oops
- * is considered a "success", a failure is to just skip the
- * real test.
- */
- if ((*ptr & 0xAA) != 0xAA) {
- pr_info("%p was NOT written during init!?\n", ptr);
- break;
- }
-
- pr_info("attempting bad ro_after_init write at %p\n", ptr);
- *ptr ^= 0xabcd1234;
-
- break;
- }
- case CT_WRITE_KERN: {
- size_t size;
- unsigned char *ptr;
-
- size = (unsigned long)do_overwritten -
- (unsigned long)do_nothing;
- ptr = (unsigned char *)do_overwritten;
-
- pr_info("attempting bad %zu byte write at %p\n", size, ptr);
- memcpy(ptr, (unsigned char *)do_nothing, size);
- flush_icache_range((unsigned long)ptr,
- (unsigned long)(ptr + size));
-
- do_overwritten();
- break;
- }
- case CT_WRAP_ATOMIC: {
- atomic_t under = ATOMIC_INIT(INT_MIN);
- atomic_t over = ATOMIC_INIT(INT_MAX);
-
- pr_info("attempting atomic underflow\n");
- atomic_dec(&under);
- pr_info("attempting atomic overflow\n");
- atomic_inc(&over);
-
- return;
- }
- case CT_NONE:
- default:
- break;
- }
-
-}
-
-static void lkdtm_handler(void)
-{
- unsigned long flags;
- bool do_it = false;
-
- spin_lock_irqsave(&count_lock, flags);
- count--;
- pr_info("Crash point %s of type %s hit, trigger in %d rounds\n",
- cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
-
- if (count == 0) {
- do_it = true;
- count = cpoint_count;
- }
- spin_unlock_irqrestore(&count_lock, flags);
-
- if (do_it)
- lkdtm_do_action(cptype);
-}
-
-static int lkdtm_register_cpoint(enum cname which)
-{
- int ret;
-
- cpoint = CN_INVALID;
- if (lkdtm.entry != NULL)
- unregister_jprobe(&lkdtm);
-
- switch (which) {
- case CN_DIRECT:
- lkdtm_do_action(cptype);
- return 0;
- case CN_INT_HARDWARE_ENTRY:
- lkdtm.kp.symbol_name = "do_IRQ";
- lkdtm.entry = (kprobe_opcode_t*) jp_do_irq;
- break;
- case CN_INT_HW_IRQ_EN:
- lkdtm.kp.symbol_name = "handle_IRQ_event";
- lkdtm.entry = (kprobe_opcode_t*) jp_handle_irq_event;
- break;
- case CN_INT_TASKLET_ENTRY:
- lkdtm.kp.symbol_name = "tasklet_action";
- lkdtm.entry = (kprobe_opcode_t*) jp_tasklet_action;
- break;
- case CN_FS_DEVRW:
- lkdtm.kp.symbol_name = "ll_rw_block";
- lkdtm.entry = (kprobe_opcode_t*) jp_ll_rw_block;
- break;
- case CN_MEM_SWAPOUT:
- lkdtm.kp.symbol_name = "shrink_inactive_list";
- lkdtm.entry = (kprobe_opcode_t*) jp_shrink_inactive_list;
- break;
- case CN_TIMERADD:
- lkdtm.kp.symbol_name = "hrtimer_start";
- lkdtm.entry = (kprobe_opcode_t*) jp_hrtimer_start;
- break;
- case CN_SCSI_DISPATCH_CMD:
- lkdtm.kp.symbol_name = "scsi_dispatch_cmd";
- lkdtm.entry = (kprobe_opcode_t*) jp_scsi_dispatch_cmd;
- break;
- case CN_IDE_CORE_CP:
-#ifdef CONFIG_IDE
- lkdtm.kp.symbol_name = "generic_ide_ioctl";
- lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl;
-#else
- pr_info("Crash point not available\n");
- return -EINVAL;
-#endif
- break;
- default:
- pr_info("Invalid Crash Point\n");
- return -EINVAL;
- }
-
- cpoint = which;
- if ((ret = register_jprobe(&lkdtm)) < 0) {
- pr_info("Couldn't register jprobe\n");
- cpoint = CN_INVALID;
- }
-
- return ret;
-}
-
-static ssize_t do_register_entry(enum cname which, struct file *f,
- const char __user *user_buf, size_t count, loff_t *off)
-{
- char *buf;
- int err;
-
- if (count >= PAGE_SIZE)
- return -EINVAL;
-
- buf = (char *)__get_free_page(GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- if (copy_from_user(buf, user_buf, count)) {
- free_page((unsigned long) buf);
- return -EFAULT;
- }
- /* NULL-terminate and remove enter */
- buf[count] = '\0';
- strim(buf);
-
- cptype = parse_cp_type(buf, count);
- free_page((unsigned long) buf);
-
- if (cptype == CT_NONE)
- return -EINVAL;
-
- err = lkdtm_register_cpoint(which);
- if (err < 0)
- return err;
-
- *off += count;
-
- return count;
-}
-
-/* Generic read callback that just prints out the available crash types */
-static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
- size_t count, loff_t *off)
-{
- char *buf;
- int i, n, out;
-
- buf = (char *)__get_free_page(GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- n = snprintf(buf, PAGE_SIZE, "Available crash types:\n");
- for (i = 0; i < ARRAY_SIZE(cp_type); i++)
- n += snprintf(buf + n, PAGE_SIZE - n, "%s\n", cp_type[i]);
- buf[n] = '\0';
-
- out = simple_read_from_buffer(user_buf, count, off,
- buf, n);
- free_page((unsigned long) buf);
-
- return out;
-}
-
-static int lkdtm_debugfs_open(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-
-static ssize_t int_hardware_entry(struct file *f, const char __user *buf,
- size_t count, loff_t *off)
-{
- return do_register_entry(CN_INT_HARDWARE_ENTRY, f, buf, count, off);
-}
-
-static ssize_t int_hw_irq_en(struct file *f, const char __user *buf,
- size_t count, loff_t *off)
-{
- return do_register_entry(CN_INT_HW_IRQ_EN, f, buf, count, off);
-}
-
-static ssize_t int_tasklet_entry(struct file *f, const char __user *buf,
- size_t count, loff_t *off)
-{
- return do_register_entry(CN_INT_TASKLET_ENTRY, f, buf, count, off);
-}
-
-static ssize_t fs_devrw_entry(struct file *f, const char __user *buf,
- size_t count, loff_t *off)
-{
- return do_register_entry(CN_FS_DEVRW, f, buf, count, off);
-}
-
-static ssize_t mem_swapout_entry(struct file *f, const char __user *buf,
- size_t count, loff_t *off)
-{
- return do_register_entry(CN_MEM_SWAPOUT, f, buf, count, off);
-}
-
-static ssize_t timeradd_entry(struct file *f, const char __user *buf,
- size_t count, loff_t *off)
-{
- return do_register_entry(CN_TIMERADD, f, buf, count, off);
-}
-
-static ssize_t scsi_dispatch_cmd_entry(struct file *f,
- const char __user *buf, size_t count, loff_t *off)
-{
- return do_register_entry(CN_SCSI_DISPATCH_CMD, f, buf, count, off);
-}
-
-static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf,
- size_t count, loff_t *off)
-{
- return do_register_entry(CN_IDE_CORE_CP, f, buf, count, off);
-}
-
-/* Special entry to just crash directly. Available without KPROBEs */
-static ssize_t direct_entry(struct file *f, const char __user *user_buf,
- size_t count, loff_t *off)
-{
- enum ctype type;
- char *buf;
-
- if (count >= PAGE_SIZE)
- return -EINVAL;
- if (count < 1)
- return -EINVAL;
-
- buf = (char *)__get_free_page(GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- if (copy_from_user(buf, user_buf, count)) {
- free_page((unsigned long) buf);
- return -EFAULT;
- }
- /* NULL-terminate and remove enter */
- buf[count] = '\0';
- strim(buf);
-
- type = parse_cp_type(buf, count);
- free_page((unsigned long) buf);
- if (type == CT_NONE)
- return -EINVAL;
-
- pr_info("Performing direct entry %s\n", cp_type_to_str(type));
- lkdtm_do_action(type);
- *off += count;
-
- return count;
-}
-
-struct crash_entry {
- const char *name;
- const struct file_operations fops;
-};
-
-static const struct crash_entry crash_entries[] = {
- {"DIRECT", {.read = lkdtm_debugfs_read,
- .llseek = generic_file_llseek,
- .open = lkdtm_debugfs_open,
- .write = direct_entry} },
- {"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read,
- .llseek = generic_file_llseek,
- .open = lkdtm_debugfs_open,
- .write = int_hardware_entry} },
- {"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read,
- .llseek = generic_file_llseek,
- .open = lkdtm_debugfs_open,
- .write = int_hw_irq_en} },
- {"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read,
- .llseek = generic_file_llseek,
- .open = lkdtm_debugfs_open,
- .write = int_tasklet_entry} },
- {"FS_DEVRW", {.read = lkdtm_debugfs_read,
- .llseek = generic_file_llseek,
- .open = lkdtm_debugfs_open,
- .write = fs_devrw_entry} },
- {"MEM_SWAPOUT", {.read = lkdtm_debugfs_read,
- .llseek = generic_file_llseek,
- .open = lkdtm_debugfs_open,
- .write = mem_swapout_entry} },
- {"TIMERADD", {.read = lkdtm_debugfs_read,
- .llseek = generic_file_llseek,
- .open = lkdtm_debugfs_open,
- .write = timeradd_entry} },
- {"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read,
- .llseek = generic_file_llseek,
- .open = lkdtm_debugfs_open,
- .write = scsi_dispatch_cmd_entry} },
- {"IDE_CORE_CP", {.read = lkdtm_debugfs_read,
- .llseek = generic_file_llseek,
- .open = lkdtm_debugfs_open,
- .write = ide_core_cp_entry} },
-};
-
-static struct dentry *lkdtm_debugfs_root;
-
-static int __init lkdtm_module_init(void)
-{
- int ret = -EINVAL;
- int n_debugfs_entries = 1; /* Assume only the direct entry */
- int i;
-
- /* Make sure we can write to __ro_after_init values during __init */
- ro_after_init |= 0xAA;
-
- /* Register debugfs interface */
- lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
- if (!lkdtm_debugfs_root) {
- pr_err("creating root dir failed\n");
- return -ENODEV;
- }
-
-#ifdef CONFIG_KPROBES
- n_debugfs_entries = ARRAY_SIZE(crash_entries);
-#endif
-
- for (i = 0; i < n_debugfs_entries; i++) {
- const struct crash_entry *cur = &crash_entries[i];
- struct dentry *de;
-
- de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root,
- NULL, &cur->fops);
- if (de == NULL) {
- pr_err("could not create %s\n", cur->name);
- goto out_err;
- }
- }
-
- if (lkdtm_parse_commandline() == -EINVAL) {
- pr_info("Invalid command\n");
- goto out_err;
- }
-
- if (cpoint != CN_INVALID && cptype != CT_NONE) {
- ret = lkdtm_register_cpoint(cpoint);
- if (ret < 0) {
- pr_info("Invalid crash point %d\n", cpoint);
- goto out_err;
- }
- pr_info("Crash point %s of type %s registered\n",
- cpoint_name, cpoint_type);
- } else {
- pr_info("No crash points registered, enable through debugfs\n");
- }
-
- return 0;
-
-out_err:
- debugfs_remove_recursive(lkdtm_debugfs_root);
- return ret;
-}
-
-static void __exit lkdtm_module_exit(void)
-{
- debugfs_remove_recursive(lkdtm_debugfs_root);
-
- unregister_jprobe(&lkdtm);
- pr_info("Crash point unregistered\n");
-}
-
-module_init(lkdtm_module_init);
-module_exit(lkdtm_module_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Kprobe module for testing crash dumps");
diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c
deleted file mode 100644
index 4a6a1d138..000000000
--- a/drivers/mmc/host/sdhci-bcm2835.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * BCM2835 SDHCI
- * Copyright (C) 2012 Stephen Warren
- * Based on U-Boot's MMC driver for the BCM2835 by Oleksandr Tymoshenko & me
- * Portions of the code there were obviously based on the Linux kernel at:
- * git://github.com/raspberrypi/linux.git rpi-3.6.y
- * commit f5b930b "Main bcm2708 linux port" signed-off-by Dom Cobley.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/mmc/host.h>
-#include "sdhci-pltfm.h"
-
-/*
- * 400KHz is max freq for card ID etc. Use that as min card clock. We need to
- * know the min to enable static calculation of max BCM2835_SDHCI_WRITE_DELAY.
- */
-#define MIN_FREQ 400000
-
-/*
- * The Arasan has a bugette whereby it may lose the content of successive
- * writes to registers that are within two SD-card clock cycles of each other
- * (a clock domain crossing problem). It seems, however, that the data
- * register does not have this problem, which is just as well - otherwise we'd
- * have to nobble the DMA engine too.
- *
- * This should probably be dynamically calculated based on the actual card
- * frequency. However, this is the longest we'll have to wait, and doesn't
- * seem to slow access down too much, so the added complexity doesn't seem
- * worth it for now.
- *
- * 1/MIN_FREQ is (max) time per tick of eMMC clock.
- * 2/MIN_FREQ is time for two ticks.
- * Multiply by 1000000 to get uS per two ticks.
- * *1000000 for uSecs.
- * +1 for hack rounding.
- */
-#define BCM2835_SDHCI_WRITE_DELAY (((2 * 1000000) / MIN_FREQ) + 1)
-
-struct bcm2835_sdhci {
- u32 shadow;
-};
-
-static void bcm2835_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
-{
- writel(val, host->ioaddr + reg);
-
- udelay(BCM2835_SDHCI_WRITE_DELAY);
-}
-
-static inline u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg)
-{
- u32 val = readl(host->ioaddr + reg);
-
- if (reg == SDHCI_CAPABILITIES)
- val |= SDHCI_CAN_VDD_330;
-
- return val;
-}
-
-static void bcm2835_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct bcm2835_sdhci *bcm2835_host = sdhci_pltfm_priv(pltfm_host);
- u32 oldval = (reg == SDHCI_COMMAND) ? bcm2835_host->shadow :
- bcm2835_sdhci_readl(host, reg & ~3);
- u32 word_num = (reg >> 1) & 1;
- u32 word_shift = word_num * 16;
- u32 mask = 0xffff << word_shift;
- u32 newval = (oldval & ~mask) | (val << word_shift);
-
- if (reg == SDHCI_TRANSFER_MODE)
- bcm2835_host->shadow = newval;
- else
- bcm2835_sdhci_writel(host, newval, reg & ~3);
-}
-
-static u16 bcm2835_sdhci_readw(struct sdhci_host *host, int reg)
-{
- u32 val = bcm2835_sdhci_readl(host, (reg & ~3));
- u32 word_num = (reg >> 1) & 1;
- u32 word_shift = word_num * 16;
- u32 word = (val >> word_shift) & 0xffff;
-
- return word;
-}
-
-static void bcm2835_sdhci_writeb(struct sdhci_host *host, u8 val, int reg)
-{
- u32 oldval = bcm2835_sdhci_readl(host, reg & ~3);
- u32 byte_num = reg & 3;
- u32 byte_shift = byte_num * 8;
- u32 mask = 0xff << byte_shift;
- u32 newval = (oldval & ~mask) | (val << byte_shift);
-
- bcm2835_sdhci_writel(host, newval, reg & ~3);
-}
-
-static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg)
-{
- u32 val = bcm2835_sdhci_readl(host, (reg & ~3));
- u32 byte_num = reg & 3;
- u32 byte_shift = byte_num * 8;
- u32 byte = (val >> byte_shift) & 0xff;
-
- return byte;
-}
-
-static unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
-{
- return MIN_FREQ;
-}
-
-static const struct sdhci_ops bcm2835_sdhci_ops = {
- .write_l = bcm2835_sdhci_writel,
- .write_w = bcm2835_sdhci_writew,
- .write_b = bcm2835_sdhci_writeb,
- .read_l = bcm2835_sdhci_readl,
- .read_w = bcm2835_sdhci_readw,
- .read_b = bcm2835_sdhci_readb,
- .set_clock = sdhci_set_clock,
- .get_max_clock = sdhci_pltfm_clk_get_max_clock,
- .get_min_clock = bcm2835_sdhci_get_min_clock,
- .set_bus_width = sdhci_set_bus_width,
- .reset = sdhci_reset,
- .set_uhs_signaling = sdhci_set_uhs_signaling,
-};
-
-static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
- .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
- SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
- .ops = &bcm2835_sdhci_ops,
-};
-
-static int bcm2835_sdhci_probe(struct platform_device *pdev)
-{
- struct sdhci_host *host;
- struct bcm2835_sdhci *bcm2835_host;
- struct sdhci_pltfm_host *pltfm_host;
- int ret;
-
- host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata,
- sizeof(*bcm2835_host));
- if (IS_ERR(host))
- return PTR_ERR(host);
-
- pltfm_host = sdhci_priv(host);
-
- pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(pltfm_host->clk)) {
- ret = PTR_ERR(pltfm_host->clk);
- goto err;
- }
- ret = clk_prepare_enable(pltfm_host->clk);
- if (ret) {
- dev_err(&pdev->dev, "failed to enable host clk\n");
- goto err;
- }
-
- ret = sdhci_add_host(host);
- if (ret)
- goto err_clk;
-
- return 0;
-err_clk:
- clk_disable_unprepare(pltfm_host->clk);
-err:
- sdhci_pltfm_free(pdev);
- return ret;
-}
-
-static const struct of_device_id bcm2835_sdhci_of_match[] = {
- { .compatible = "brcm,bcm2835-sdhci" },
- { }
-};
-MODULE_DEVICE_TABLE(of, bcm2835_sdhci_of_match);
-
-static struct platform_driver bcm2835_sdhci_driver = {
- .driver = {
- .name = "sdhci-bcm2835",
- .of_match_table = bcm2835_sdhci_of_match,
- .pm = SDHCI_PLTFM_PMOPS,
- },
- .probe = bcm2835_sdhci_probe,
- .remove = sdhci_pltfm_unregister,
-};
-module_platform_driver(bcm2835_sdhci_driver);
-
-MODULE_DESCRIPTION("BCM2835 SDHCI driver");
-MODULE_AUTHOR("Stephen Warren");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/rcar_can.c b/drivers/net/can/rcar_can.c
deleted file mode 100644
index 788459f6b..000000000
--- a/drivers/net/can/rcar_can.c
+++ /dev/null
@@ -1,929 +0,0 @@
-/* Renesas R-Car CAN device driver
- *
- * Copyright (C) 2013 Cogent Embedded, Inc. <source@cogentembedded.com>
- * Copyright (C) 2013 Renesas Solutions Corp.
- *
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/platform_device.h>
-#include <linux/can/led.h>
-#include <linux/can/dev.h>
-#include <linux/clk.h>
-#include <linux/can/platform/rcar_can.h>
-#include <linux/of.h>
-
-#define RCAR_CAN_DRV_NAME "rcar_can"
-
-/* Mailbox configuration:
- * mailbox 60 - 63 - Rx FIFO mailboxes
- * mailbox 56 - 59 - Tx FIFO mailboxes
- * non-FIFO mailboxes are not used
- */
-#define RCAR_CAN_N_MBX 64 /* Number of mailboxes in non-FIFO mode */
-#define RCAR_CAN_RX_FIFO_MBX 60 /* Mailbox - window to Rx FIFO */
-#define RCAR_CAN_TX_FIFO_MBX 56 /* Mailbox - window to Tx FIFO */
-#define RCAR_CAN_FIFO_DEPTH 4
-
-/* Mailbox registers structure */
-struct rcar_can_mbox_regs {
- u32 id; /* IDE and RTR bits, SID and EID */
- u8 stub; /* Not used */
- u8 dlc; /* Data Length Code - bits [0..3] */
- u8 data[8]; /* Data Bytes */
- u8 tsh; /* Time Stamp Higher Byte */
- u8 tsl; /* Time Stamp Lower Byte */
-};
-
-struct rcar_can_regs {
- struct rcar_can_mbox_regs mb[RCAR_CAN_N_MBX]; /* Mailbox registers */
- u32 mkr_2_9[8]; /* Mask Registers 2-9 */
- u32 fidcr[2]; /* FIFO Received ID Compare Register */
- u32 mkivlr1; /* Mask Invalid Register 1 */
- u32 mier1; /* Mailbox Interrupt Enable Register 1 */
- u32 mkr_0_1[2]; /* Mask Registers 0-1 */
- u32 mkivlr0; /* Mask Invalid Register 0*/
- u32 mier0; /* Mailbox Interrupt Enable Register 0 */
- u8 pad_440[0x3c0];
- u8 mctl[64]; /* Message Control Registers */
- u16 ctlr; /* Control Register */
- u16 str; /* Status register */
- u8 bcr[3]; /* Bit Configuration Register */
- u8 clkr; /* Clock Select Register */
- u8 rfcr; /* Receive FIFO Control Register */
- u8 rfpcr; /* Receive FIFO Pointer Control Register */
- u8 tfcr; /* Transmit FIFO Control Register */
- u8 tfpcr; /* Transmit FIFO Pointer Control Register */
- u8 eier; /* Error Interrupt Enable Register */
- u8 eifr; /* Error Interrupt Factor Judge Register */
- u8 recr; /* Receive Error Count Register */
- u8 tecr; /* Transmit Error Count Register */
- u8 ecsr; /* Error Code Store Register */
- u8 cssr; /* Channel Search Support Register */
- u8 mssr; /* Mailbox Search Status Register */
- u8 msmr; /* Mailbox Search Mode Register */
- u16 tsr; /* Time Stamp Register */
- u8 afsr; /* Acceptance Filter Support Register */
- u8 pad_857;
- u8 tcr; /* Test Control Register */
- u8 pad_859[7];
- u8 ier; /* Interrupt Enable Register */
- u8 isr; /* Interrupt Status Register */
- u8 pad_862;
- u8 mbsmr; /* Mailbox Search Mask Register */
-};
-
-struct rcar_can_priv {
- struct can_priv can; /* Must be the first member! */
- struct net_device *ndev;
- struct napi_struct napi;
- struct rcar_can_regs __iomem *regs;
- struct clk *clk;
- struct clk *can_clk;
- u8 tx_dlc[RCAR_CAN_FIFO_DEPTH];
- u32 tx_head;
- u32 tx_tail;
- u8 clock_select;
- u8 ier;
-};
-
-static const struct can_bittiming_const rcar_can_bittiming_const = {
- .name = RCAR_CAN_DRV_NAME,
- .tseg1_min = 4,
- .tseg1_max = 16,
- .tseg2_min = 2,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 1024,
- .brp_inc = 1,
-};
-
-/* Control Register bits */
-#define RCAR_CAN_CTLR_BOM (3 << 11) /* Bus-Off Recovery Mode Bits */
-#define RCAR_CAN_CTLR_BOM_ENT (1 << 11) /* Entry to halt mode */
- /* at bus-off entry */
-#define RCAR_CAN_CTLR_SLPM (1 << 10)
-#define RCAR_CAN_CTLR_CANM (3 << 8) /* Operating Mode Select Bit */
-#define RCAR_CAN_CTLR_CANM_HALT (1 << 9)
-#define RCAR_CAN_CTLR_CANM_RESET (1 << 8)
-#define RCAR_CAN_CTLR_CANM_FORCE_RESET (3 << 8)
-#define RCAR_CAN_CTLR_MLM (1 << 3) /* Message Lost Mode Select */
-#define RCAR_CAN_CTLR_IDFM (3 << 1) /* ID Format Mode Select Bits */
-#define RCAR_CAN_CTLR_IDFM_MIXED (1 << 2) /* Mixed ID mode */
-#define RCAR_CAN_CTLR_MBM (1 << 0) /* Mailbox Mode select */
-
-/* Status Register bits */
-#define RCAR_CAN_STR_RSTST (1 << 8) /* Reset Status Bit */
-
-/* FIFO Received ID Compare Registers 0 and 1 bits */
-#define RCAR_CAN_FIDCR_IDE (1 << 31) /* ID Extension Bit */
-#define RCAR_CAN_FIDCR_RTR (1 << 30) /* Remote Transmission Request Bit */
-
-/* Receive FIFO Control Register bits */
-#define RCAR_CAN_RFCR_RFEST (1 << 7) /* Receive FIFO Empty Status Flag */
-#define RCAR_CAN_RFCR_RFE (1 << 0) /* Receive FIFO Enable */
-
-/* Transmit FIFO Control Register bits */
-#define RCAR_CAN_TFCR_TFUST (7 << 1) /* Transmit FIFO Unsent Message */
- /* Number Status Bits */
-#define RCAR_CAN_TFCR_TFUST_SHIFT 1 /* Offset of Transmit FIFO Unsent */
- /* Message Number Status Bits */
-#define RCAR_CAN_TFCR_TFE (1 << 0) /* Transmit FIFO Enable */
-
-#define RCAR_CAN_N_RX_MKREGS1 2 /* Number of mask registers */
- /* for Rx mailboxes 0-31 */
-#define RCAR_CAN_N_RX_MKREGS2 8
-
-/* Bit Configuration Register settings */
-#define RCAR_CAN_BCR_TSEG1(x) (((x) & 0x0f) << 20)
-#define RCAR_CAN_BCR_BPR(x) (((x) & 0x3ff) << 8)
-#define RCAR_CAN_BCR_SJW(x) (((x) & 0x3) << 4)
-#define RCAR_CAN_BCR_TSEG2(x) ((x) & 0x07)
-
-/* Mailbox and Mask Registers bits */
-#define RCAR_CAN_IDE (1 << 31)
-#define RCAR_CAN_RTR (1 << 30)
-#define RCAR_CAN_SID_SHIFT 18
-
-/* Mailbox Interrupt Enable Register 1 bits */
-#define RCAR_CAN_MIER1_RXFIE (1 << 28) /* Receive FIFO Interrupt Enable */
-#define RCAR_CAN_MIER1_TXFIE (1 << 24) /* Transmit FIFO Interrupt Enable */
-
-/* Interrupt Enable Register bits */
-#define RCAR_CAN_IER_ERSIE (1 << 5) /* Error (ERS) Interrupt Enable Bit */
-#define RCAR_CAN_IER_RXFIE (1 << 4) /* Reception FIFO Interrupt */
- /* Enable Bit */
-#define RCAR_CAN_IER_TXFIE (1 << 3) /* Transmission FIFO Interrupt */
- /* Enable Bit */
-/* Interrupt Status Register bits */
-#define RCAR_CAN_ISR_ERSF (1 << 5) /* Error (ERS) Interrupt Status Bit */
-#define RCAR_CAN_ISR_RXFF (1 << 4) /* Reception FIFO Interrupt */
- /* Status Bit */
-#define RCAR_CAN_ISR_TXFF (1 << 3) /* Transmission FIFO Interrupt */
- /* Status Bit */
-
-/* Error Interrupt Enable Register bits */
-#define RCAR_CAN_EIER_BLIE (1 << 7) /* Bus Lock Interrupt Enable */
-#define RCAR_CAN_EIER_OLIE (1 << 6) /* Overload Frame Transmit */
- /* Interrupt Enable */
-#define RCAR_CAN_EIER_ORIE (1 << 5) /* Receive Overrun Interrupt Enable */
-#define RCAR_CAN_EIER_BORIE (1 << 4) /* Bus-Off Recovery Interrupt Enable */
-#define RCAR_CAN_EIER_BOEIE (1 << 3) /* Bus-Off Entry Interrupt Enable */
-#define RCAR_CAN_EIER_EPIE (1 << 2) /* Error Passive Interrupt Enable */
-#define RCAR_CAN_EIER_EWIE (1 << 1) /* Error Warning Interrupt Enable */
-#define RCAR_CAN_EIER_BEIE (1 << 0) /* Bus Error Interrupt Enable */
-
-/* Error Interrupt Factor Judge Register bits */
-#define RCAR_CAN_EIFR_BLIF (1 << 7) /* Bus Lock Detect Flag */
-#define RCAR_CAN_EIFR_OLIF (1 << 6) /* Overload Frame Transmission */
- /* Detect Flag */
-#define RCAR_CAN_EIFR_ORIF (1 << 5) /* Receive Overrun Detect Flag */
-#define RCAR_CAN_EIFR_BORIF (1 << 4) /* Bus-Off Recovery Detect Flag */
-#define RCAR_CAN_EIFR_BOEIF (1 << 3) /* Bus-Off Entry Detect Flag */
-#define RCAR_CAN_EIFR_EPIF (1 << 2) /* Error Passive Detect Flag */
-#define RCAR_CAN_EIFR_EWIF (1 << 1) /* Error Warning Detect Flag */
-#define RCAR_CAN_EIFR_BEIF (1 << 0) /* Bus Error Detect Flag */
-
-/* Error Code Store Register bits */
-#define RCAR_CAN_ECSR_EDPM (1 << 7) /* Error Display Mode Select Bit */
-#define RCAR_CAN_ECSR_ADEF (1 << 6) /* ACK Delimiter Error Flag */
-#define RCAR_CAN_ECSR_BE0F (1 << 5) /* Bit Error (dominant) Flag */
-#define RCAR_CAN_ECSR_BE1F (1 << 4) /* Bit Error (recessive) Flag */
-#define RCAR_CAN_ECSR_CEF (1 << 3) /* CRC Error Flag */
-#define RCAR_CAN_ECSR_AEF (1 << 2) /* ACK Error Flag */
-#define RCAR_CAN_ECSR_FEF (1 << 1) /* Form Error Flag */
-#define RCAR_CAN_ECSR_SEF (1 << 0) /* Stuff Error Flag */
-
-#define RCAR_CAN_NAPI_WEIGHT 4
-#define MAX_STR_READS 0x100
-
-static void tx_failure_cleanup(struct net_device *ndev)
-{
- int i;
-
- for (i = 0; i < RCAR_CAN_FIFO_DEPTH; i++)
- can_free_echo_skb(ndev, i);
-}
-
-static void rcar_can_error(struct net_device *ndev)
-{
- struct rcar_can_priv *priv = netdev_priv(ndev);
- struct net_device_stats *stats = &ndev->stats;
- struct can_frame *cf;
- struct sk_buff *skb;
- u8 eifr, txerr = 0, rxerr = 0;
-
- /* Propagate the error condition to the CAN stack */
- skb = alloc_can_err_skb(ndev, &cf);
-
- eifr = readb(&priv->regs->eifr);
- if (eifr & (RCAR_CAN_EIFR_EWIF | RCAR_CAN_EIFR_EPIF)) {
- txerr = readb(&priv->regs->tecr);
- rxerr = readb(&priv->regs->recr);
- if (skb) {
- cf->can_id |= CAN_ERR_CRTL;
- cf->data[6] = txerr;
- cf->data[7] = rxerr;
- }
- }
- if (eifr & RCAR_CAN_EIFR_BEIF) {
- int rx_errors = 0, tx_errors = 0;
- u8 ecsr;
-
- netdev_dbg(priv->ndev, "Bus error interrupt:\n");
- if (skb)
- cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
-
- ecsr = readb(&priv->regs->ecsr);
- if (ecsr & RCAR_CAN_ECSR_ADEF) {
- netdev_dbg(priv->ndev, "ACK Delimiter Error\n");
- tx_errors++;
- writeb(~RCAR_CAN_ECSR_ADEF, &priv->regs->ecsr);
- if (skb)
- cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL;
- }
- if (ecsr & RCAR_CAN_ECSR_BE0F) {
- netdev_dbg(priv->ndev, "Bit Error (dominant)\n");
- tx_errors++;
- writeb(~RCAR_CAN_ECSR_BE0F, &priv->regs->ecsr);
- if (skb)
- cf->data[2] |= CAN_ERR_PROT_BIT0;
- }
- if (ecsr & RCAR_CAN_ECSR_BE1F) {
- netdev_dbg(priv->ndev, "Bit Error (recessive)\n");
- tx_errors++;
- writeb(~RCAR_CAN_ECSR_BE1F, &priv->regs->ecsr);
- if (skb)
- cf->data[2] |= CAN_ERR_PROT_BIT1;
- }
- if (ecsr & RCAR_CAN_ECSR_CEF) {
- netdev_dbg(priv->ndev, "CRC Error\n");
- rx_errors++;
- writeb(~RCAR_CAN_ECSR_CEF, &priv->regs->ecsr);
- if (skb)
- cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
- }
- if (ecsr & RCAR_CAN_ECSR_AEF) {
- netdev_dbg(priv->ndev, "ACK Error\n");
- tx_errors++;
- writeb(~RCAR_CAN_ECSR_AEF, &priv->regs->ecsr);
- if (skb) {
- cf->can_id |= CAN_ERR_ACK;
- cf->data[3] = CAN_ERR_PROT_LOC_ACK;
- }
- }
- if (ecsr & RCAR_CAN_ECSR_FEF) {
- netdev_dbg(priv->ndev, "Form Error\n");
- rx_errors++;
- writeb(~RCAR_CAN_ECSR_FEF, &priv->regs->ecsr);
- if (skb)
- cf->data[2] |= CAN_ERR_PROT_FORM;
- }
- if (ecsr & RCAR_CAN_ECSR_SEF) {
- netdev_dbg(priv->ndev, "Stuff Error\n");
- rx_errors++;
- writeb(~RCAR_CAN_ECSR_SEF, &priv->regs->ecsr);
- if (skb)
- cf->data[2] |= CAN_ERR_PROT_STUFF;
- }
-
- priv->can.can_stats.bus_error++;
- ndev->stats.rx_errors += rx_errors;
- ndev->stats.tx_errors += tx_errors;
- writeb(~RCAR_CAN_EIFR_BEIF, &priv->regs->eifr);
- }
- if (eifr & RCAR_CAN_EIFR_EWIF) {
- netdev_dbg(priv->ndev, "Error warning interrupt\n");
- priv->can.state = CAN_STATE_ERROR_WARNING;
- priv->can.can_stats.error_warning++;
- /* Clear interrupt condition */
- writeb(~RCAR_CAN_EIFR_EWIF, &priv->regs->eifr);
- if (skb)
- cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_WARNING :
- CAN_ERR_CRTL_RX_WARNING;
- }
- if (eifr & RCAR_CAN_EIFR_EPIF) {
- netdev_dbg(priv->ndev, "Error passive interrupt\n");
- priv->can.state = CAN_STATE_ERROR_PASSIVE;
- priv->can.can_stats.error_passive++;
- /* Clear interrupt condition */
- writeb(~RCAR_CAN_EIFR_EPIF, &priv->regs->eifr);
- if (skb)
- cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_PASSIVE :
- CAN_ERR_CRTL_RX_PASSIVE;
- }
- if (eifr & RCAR_CAN_EIFR_BOEIF) {
- netdev_dbg(priv->ndev, "Bus-off entry interrupt\n");
- tx_failure_cleanup(ndev);
- priv->ier = RCAR_CAN_IER_ERSIE;
- writeb(priv->ier, &priv->regs->ier);
- priv->can.state = CAN_STATE_BUS_OFF;
- /* Clear interrupt condition */
- writeb(~RCAR_CAN_EIFR_BOEIF, &priv->regs->eifr);
- priv->can.can_stats.bus_off++;
- can_bus_off(ndev);
- if (skb)
- cf->can_id |= CAN_ERR_BUSOFF;
- }
- if (eifr & RCAR_CAN_EIFR_ORIF) {
- netdev_dbg(priv->ndev, "Receive overrun error interrupt\n");
- ndev->stats.rx_over_errors++;
- ndev->stats.rx_errors++;
- writeb(~RCAR_CAN_EIFR_ORIF, &priv->regs->eifr);
- if (skb) {
- cf->can_id |= CAN_ERR_CRTL;
- cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
- }
- }
- if (eifr & RCAR_CAN_EIFR_OLIF) {
- netdev_dbg(priv->ndev,
- "Overload Frame Transmission error interrupt\n");
- ndev->stats.rx_over_errors++;
- ndev->stats.rx_errors++;
- writeb(~RCAR_CAN_EIFR_OLIF, &priv->regs->eifr);
- if (skb) {
- cf->can_id |= CAN_ERR_PROT;
- cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
- }
- }
-
- if (skb) {
- stats->rx_packets++;
- stats->rx_bytes += cf->can_dlc;
- netif_rx(skb);
- }
-}
-
-static void rcar_can_tx_done(struct net_device *ndev)
-{
- struct rcar_can_priv *priv = netdev_priv(ndev);
- struct net_device_stats *stats = &ndev->stats;
- u8 isr;
-
- while (1) {
- u8 unsent = readb(&priv->regs->tfcr);
-
- unsent = (unsent & RCAR_CAN_TFCR_TFUST) >>
- RCAR_CAN_TFCR_TFUST_SHIFT;
- if (priv->tx_head - priv->tx_tail <= unsent)
- break;
- stats->tx_packets++;
- stats->tx_bytes += priv->tx_dlc[priv->tx_tail %
- RCAR_CAN_FIFO_DEPTH];
- priv->tx_dlc[priv->tx_tail % RCAR_CAN_FIFO_DEPTH] = 0;
- can_get_echo_skb(ndev, priv->tx_tail % RCAR_CAN_FIFO_DEPTH);
- priv->tx_tail++;
- netif_wake_queue(ndev);
- }
- /* Clear interrupt */
- isr = readb(&priv->regs->isr);
- writeb(isr & ~RCAR_CAN_ISR_TXFF, &priv->regs->isr);
- can_led_event(ndev, CAN_LED_EVENT_TX);
-}
-
-static irqreturn_t rcar_can_interrupt(int irq, void *dev_id)
-{
- struct net_device *ndev = dev_id;
- struct rcar_can_priv *priv = netdev_priv(ndev);
- u8 isr;
-
- isr = readb(&priv->regs->isr);
- if (!(isr & priv->ier))
- return IRQ_NONE;
-
- if (isr & RCAR_CAN_ISR_ERSF)
- rcar_can_error(ndev);
-
- if (isr & RCAR_CAN_ISR_TXFF)
- rcar_can_tx_done(ndev);
-
- if (isr & RCAR_CAN_ISR_RXFF) {
- if (napi_schedule_prep(&priv->napi)) {
- /* Disable Rx FIFO interrupts */
- priv->ier &= ~RCAR_CAN_IER_RXFIE;
- writeb(priv->ier, &priv->regs->ier);
- __napi_schedule(&priv->napi);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static void rcar_can_set_bittiming(struct net_device *dev)
-{
- struct rcar_can_priv *priv = netdev_priv(dev);
- struct can_bittiming *bt = &priv->can.bittiming;
- u32 bcr;
-
- bcr = RCAR_CAN_BCR_TSEG1(bt->phase_seg1 + bt->prop_seg - 1) |
- RCAR_CAN_BCR_BPR(bt->brp - 1) | RCAR_CAN_BCR_SJW(bt->sjw - 1) |
- RCAR_CAN_BCR_TSEG2(bt->phase_seg2 - 1);
- /* Don't overwrite CLKR with 32-bit BCR access; CLKR has 8-bit access.
- * All the registers are big-endian but they get byte-swapped on 32-bit
- * read/write (but not on 8-bit, contrary to the manuals)...
- */
- writel((bcr << 8) | priv->clock_select, &priv->regs->bcr);
-}
-
-static void rcar_can_start(struct net_device *ndev)
-{
- struct rcar_can_priv *priv = netdev_priv(ndev);
- u16 ctlr;
- int i;
-
- /* Set controller to known mode:
- * - FIFO mailbox mode
- * - accept all messages
- * - overrun mode
- * CAN is in sleep mode after MCU hardware or software reset.
- */
- ctlr = readw(&priv->regs->ctlr);
- ctlr &= ~RCAR_CAN_CTLR_SLPM;
- writew(ctlr, &priv->regs->ctlr);
- /* Go to reset mode */
- ctlr |= RCAR_CAN_CTLR_CANM_FORCE_RESET;
- writew(ctlr, &priv->regs->ctlr);
- for (i = 0; i < MAX_STR_READS; i++) {
- if (readw(&priv->regs->str) & RCAR_CAN_STR_RSTST)
- break;
- }
- rcar_can_set_bittiming(ndev);
- ctlr |= RCAR_CAN_CTLR_IDFM_MIXED; /* Select mixed ID mode */
- ctlr |= RCAR_CAN_CTLR_BOM_ENT; /* Entry to halt mode automatically */
- /* at bus-off */
- ctlr |= RCAR_CAN_CTLR_MBM; /* Select FIFO mailbox mode */
- ctlr |= RCAR_CAN_CTLR_MLM; /* Overrun mode */
- writew(ctlr, &priv->regs->ctlr);
-
- /* Accept all SID and EID */
- writel(0, &priv->regs->mkr_2_9[6]);
- writel(0, &priv->regs->mkr_2_9[7]);
- /* In FIFO mailbox mode, write "0" to bits 24 to 31 */
- writel(0, &priv->regs->mkivlr1);
- /* Accept all frames */
- writel(0, &priv->regs->fidcr[0]);
- writel(RCAR_CAN_FIDCR_IDE | RCAR_CAN_FIDCR_RTR, &priv->regs->fidcr[1]);
- /* Enable and configure FIFO mailbox interrupts */
- writel(RCAR_CAN_MIER1_RXFIE | RCAR_CAN_MIER1_TXFIE, &priv->regs->mier1);
-
- priv->ier = RCAR_CAN_IER_ERSIE | RCAR_CAN_IER_RXFIE |
- RCAR_CAN_IER_TXFIE;
- writeb(priv->ier, &priv->regs->ier);
-
- /* Accumulate error codes */
- writeb(RCAR_CAN_ECSR_EDPM, &priv->regs->ecsr);
- /* Enable error interrupts */
- writeb(RCAR_CAN_EIER_EWIE | RCAR_CAN_EIER_EPIE | RCAR_CAN_EIER_BOEIE |
- (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING ?
- RCAR_CAN_EIER_BEIE : 0) | RCAR_CAN_EIER_ORIE |
- RCAR_CAN_EIER_OLIE, &priv->regs->eier);
- priv->can.state = CAN_STATE_ERROR_ACTIVE;
-
- /* Go to operation mode */
- writew(ctlr & ~RCAR_CAN_CTLR_CANM, &priv->regs->ctlr);
- for (i = 0; i < MAX_STR_READS; i++) {
- if (!(readw(&priv->regs->str) & RCAR_CAN_STR_RSTST))
- break;
- }
- /* Enable Rx and Tx FIFO */
- writeb(RCAR_CAN_RFCR_RFE, &priv->regs->rfcr);
- writeb(RCAR_CAN_TFCR_TFE, &priv->regs->tfcr);
-}
-
-static int rcar_can_open(struct net_device *ndev)
-{
- struct rcar_can_priv *priv = netdev_priv(ndev);
- int err;
-
- err = clk_prepare_enable(priv->clk);
- if (err) {
- netdev_err(ndev,
- "failed to enable peripheral clock, error %d\n",
- err);
- goto out;
- }
- err = clk_prepare_enable(priv->can_clk);
- if (err) {
- netdev_err(ndev, "failed to enable CAN clock, error %d\n",
- err);
- goto out_clock;
- }
- err = open_candev(ndev);
- if (err) {
- netdev_err(ndev, "open_candev() failed, error %d\n", err);
- goto out_can_clock;
- }
- napi_enable(&priv->napi);
- err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev);
- if (err) {
- netdev_err(ndev, "request_irq(%d) failed, error %d\n",
- ndev->irq, err);
- goto out_close;
- }
- can_led_event(ndev, CAN_LED_EVENT_OPEN);
- rcar_can_start(ndev);
- netif_start_queue(ndev);
- return 0;
-out_close:
- napi_disable(&priv->napi);
- close_candev(ndev);
-out_can_clock:
- clk_disable_unprepare(priv->can_clk);
-out_clock:
- clk_disable_unprepare(priv->clk);
-out:
- return err;
-}
-
-static void rcar_can_stop(struct net_device *ndev)
-{
- struct rcar_can_priv *priv = netdev_priv(ndev);
- u16 ctlr;
- int i;
-
- /* Go to (force) reset mode */
- ctlr = readw(&priv->regs->ctlr);
- ctlr |= RCAR_CAN_CTLR_CANM_FORCE_RESET;
- writew(ctlr, &priv->regs->ctlr);
- for (i = 0; i < MAX_STR_READS; i++) {
- if (readw(&priv->regs->str) & RCAR_CAN_STR_RSTST)
- break;
- }
- writel(0, &priv->regs->mier0);
- writel(0, &priv->regs->mier1);
- writeb(0, &priv->regs->ier);
- writeb(0, &priv->regs->eier);
- /* Go to sleep mode */
- ctlr |= RCAR_CAN_CTLR_SLPM;
- writew(ctlr, &priv->regs->ctlr);
- priv->can.state = CAN_STATE_STOPPED;
-}
-
-static int rcar_can_close(struct net_device *ndev)
-{
- struct rcar_can_priv *priv = netdev_priv(ndev);
-
- netif_stop_queue(ndev);
- rcar_can_stop(ndev);
- free_irq(ndev->irq, ndev);
- napi_disable(&priv->napi);
- clk_disable_unprepare(priv->can_clk);
- clk_disable_unprepare(priv->clk);
- close_candev(ndev);
- can_led_event(ndev, CAN_LED_EVENT_STOP);
- return 0;
-}
-
-static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb,
- struct net_device *ndev)
-{
- struct rcar_can_priv *priv = netdev_priv(ndev);
- struct can_frame *cf = (struct can_frame *)skb->data;
- u32 data, i;
-
- if (can_dropped_invalid_skb(ndev, skb))
- return NETDEV_TX_OK;
-
- if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
- data = (cf->can_id & CAN_EFF_MASK) | RCAR_CAN_IDE;
- else /* Standard frame format */
- data = (cf->can_id & CAN_SFF_MASK) << RCAR_CAN_SID_SHIFT;
-
- if (cf->can_id & CAN_RTR_FLAG) { /* Remote transmission request */
- data |= RCAR_CAN_RTR;
- } else {
- for (i = 0; i < cf->can_dlc; i++)
- writeb(cf->data[i],
- &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].data[i]);
- }
-
- writel(data, &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].id);
-
- writeb(cf->can_dlc, &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].dlc);
-
- priv->tx_dlc[priv->tx_head % RCAR_CAN_FIFO_DEPTH] = cf->can_dlc;
- can_put_echo_skb(skb, ndev, priv->tx_head % RCAR_CAN_FIFO_DEPTH);
- priv->tx_head++;
- /* Start Tx: write 0xff to the TFPCR register to increment
- * the CPU-side pointer for the transmit FIFO to the next
- * mailbox location
- */
- writeb(0xff, &priv->regs->tfpcr);
- /* Stop the queue if we've filled all FIFO entries */
- if (priv->tx_head - priv->tx_tail >= RCAR_CAN_FIFO_DEPTH)
- netif_stop_queue(ndev);
-
- return NETDEV_TX_OK;
-}
-
-static const struct net_device_ops rcar_can_netdev_ops = {
- .ndo_open = rcar_can_open,
- .ndo_stop = rcar_can_close,
- .ndo_start_xmit = rcar_can_start_xmit,
- .ndo_change_mtu = can_change_mtu,
-};
-
-static void rcar_can_rx_pkt(struct rcar_can_priv *priv)
-{
- struct net_device_stats *stats = &priv->ndev->stats;
- struct can_frame *cf;
- struct sk_buff *skb;
- u32 data;
- u8 dlc;
-
- skb = alloc_can_skb(priv->ndev, &cf);
- if (!skb) {
- stats->rx_dropped++;
- return;
- }
-
- data = readl(&priv->regs->mb[RCAR_CAN_RX_FIFO_MBX].id);
- if (data & RCAR_CAN_IDE)
- cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;
- else
- cf->can_id = (data >> RCAR_CAN_SID_SHIFT) & CAN_SFF_MASK;
-
- dlc = readb(&priv->regs->mb[RCAR_CAN_RX_FIFO_MBX].dlc);
- cf->can_dlc = get_can_dlc(dlc);
- if (data & RCAR_CAN_RTR) {
- cf->can_id |= CAN_RTR_FLAG;
- } else {
- for (dlc = 0; dlc < cf->can_dlc; dlc++)
- cf->data[dlc] =
- readb(&priv->regs->mb[RCAR_CAN_RX_FIFO_MBX].data[dlc]);
- }
-
- can_led_event(priv->ndev, CAN_LED_EVENT_RX);
-
- stats->rx_bytes += cf->can_dlc;
- stats->rx_packets++;
- netif_receive_skb(skb);
-}
-
-static int rcar_can_rx_poll(struct napi_struct *napi, int quota)
-{
- struct rcar_can_priv *priv = container_of(napi,
- struct rcar_can_priv, napi);
- int num_pkts;
-
- for (num_pkts = 0; num_pkts < quota; num_pkts++) {
- u8 rfcr, isr;
-
- isr = readb(&priv->regs->isr);
- /* Clear interrupt bit */
- if (isr & RCAR_CAN_ISR_RXFF)
- writeb(isr & ~RCAR_CAN_ISR_RXFF, &priv->regs->isr);
- rfcr = readb(&priv->regs->rfcr);
- if (rfcr & RCAR_CAN_RFCR_RFEST)
- break;
- rcar_can_rx_pkt(priv);
- /* Write 0xff to the RFPCR register to increment
- * the CPU-side pointer for the receive FIFO
- * to the next mailbox location
- */
- writeb(0xff, &priv->regs->rfpcr);
- }
- /* All packets processed */
- if (num_pkts < quota) {
- napi_complete(napi);
- priv->ier |= RCAR_CAN_IER_RXFIE;
- writeb(priv->ier, &priv->regs->ier);
- }
- return num_pkts;
-}
-
-static int rcar_can_do_set_mode(struct net_device *ndev, enum can_mode mode)
-{
- switch (mode) {
- case CAN_MODE_START:
- rcar_can_start(ndev);
- netif_wake_queue(ndev);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static int rcar_can_get_berr_counter(const struct net_device *dev,
- struct can_berr_counter *bec)
-{
- struct rcar_can_priv *priv = netdev_priv(dev);
- int err;
-
- err = clk_prepare_enable(priv->clk);
- if (err)
- return err;
- bec->txerr = readb(&priv->regs->tecr);
- bec->rxerr = readb(&priv->regs->recr);
- clk_disable_unprepare(priv->clk);
- return 0;
-}
-
-static const char * const clock_names[] = {
- [CLKR_CLKP1] = "clkp1",
- [CLKR_CLKP2] = "clkp2",
- [CLKR_CLKEXT] = "can_clk",
-};
-
-static int rcar_can_probe(struct platform_device *pdev)
-{
- struct rcar_can_platform_data *pdata;
- struct rcar_can_priv *priv;
- struct net_device *ndev;
- struct resource *mem;
- void __iomem *addr;
- u32 clock_select = CLKR_CLKP1;
- int err = -ENODEV;
- int irq;
-
- if (pdev->dev.of_node) {
- of_property_read_u32(pdev->dev.of_node,
- "renesas,can-clock-select", &clock_select);
- } else {
- pdata = dev_get_platdata(&pdev->dev);
- if (!pdata) {
- dev_err(&pdev->dev, "No platform data provided!\n");
- goto fail;
- }
- clock_select = pdata->clock_select;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "No IRQ resource\n");
- err = irq;
- goto fail;
- }
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- addr = devm_ioremap_resource(&pdev->dev, mem);
- if (IS_ERR(addr)) {
- err = PTR_ERR(addr);
- goto fail;
- }
-
- ndev = alloc_candev(sizeof(struct rcar_can_priv), RCAR_CAN_FIFO_DEPTH);
- if (!ndev) {
- dev_err(&pdev->dev, "alloc_candev() failed\n");
- err = -ENOMEM;
- goto fail;
- }
-
- priv = netdev_priv(ndev);
-
- priv->clk = devm_clk_get(&pdev->dev, "clkp1");
- if (IS_ERR(priv->clk)) {
- err = PTR_ERR(priv->clk);
- dev_err(&pdev->dev, "cannot get peripheral clock, error %d\n",
- err);
- goto fail_clk;
- }
-
- if (clock_select >= ARRAY_SIZE(clock_names)) {
- err = -EINVAL;
- dev_err(&pdev->dev, "invalid CAN clock selected\n");
- goto fail_clk;
- }
- priv->can_clk = devm_clk_get(&pdev->dev, clock_names[clock_select]);
- if (IS_ERR(priv->can_clk)) {
- err = PTR_ERR(priv->can_clk);
- dev_err(&pdev->dev, "cannot get CAN clock, error %d\n", err);
- goto fail_clk;
- }
-
- ndev->netdev_ops = &rcar_can_netdev_ops;
- ndev->irq = irq;
- ndev->flags |= IFF_ECHO;
- priv->ndev = ndev;
- priv->regs = addr;
- priv->clock_select = clock_select;
- priv->can.clock.freq = clk_get_rate(priv->can_clk);
- priv->can.bittiming_const = &rcar_can_bittiming_const;
- priv->can.do_set_mode = rcar_can_do_set_mode;
- priv->can.do_get_berr_counter = rcar_can_get_berr_counter;
- priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING;
- platform_set_drvdata(pdev, ndev);
- SET_NETDEV_DEV(ndev, &pdev->dev);
-
- netif_napi_add(ndev, &priv->napi, rcar_can_rx_poll,
- RCAR_CAN_NAPI_WEIGHT);
- err = register_candev(ndev);
- if (err) {
- dev_err(&pdev->dev, "register_candev() failed, error %d\n",
- err);
- goto fail_candev;
- }
-
- devm_can_led_init(ndev);
-
- dev_info(&pdev->dev, "device registered (regs @ %p, IRQ%d)\n",
- priv->regs, ndev->irq);
-
- return 0;
-fail_candev:
- netif_napi_del(&priv->napi);
-fail_clk:
- free_candev(ndev);
-fail:
- return err;
-}
-
-static int rcar_can_remove(struct platform_device *pdev)
-{
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct rcar_can_priv *priv = netdev_priv(ndev);
-
- unregister_candev(ndev);
- netif_napi_del(&priv->napi);
- free_candev(ndev);
- return 0;
-}
-
-static int __maybe_unused rcar_can_suspend(struct device *dev)
-{
- struct net_device *ndev = dev_get_drvdata(dev);
- struct rcar_can_priv *priv = netdev_priv(ndev);
- u16 ctlr;
-
- if (netif_running(ndev)) {
- netif_stop_queue(ndev);
- netif_device_detach(ndev);
- }
- ctlr = readw(&priv->regs->ctlr);
- ctlr |= RCAR_CAN_CTLR_CANM_HALT;
- writew(ctlr, &priv->regs->ctlr);
- ctlr |= RCAR_CAN_CTLR_SLPM;
- writew(ctlr, &priv->regs->ctlr);
- priv->can.state = CAN_STATE_SLEEPING;
-
- clk_disable(priv->clk);
- return 0;
-}
-
-static int __maybe_unused rcar_can_resume(struct device *dev)
-{
- struct net_device *ndev = dev_get_drvdata(dev);
- struct rcar_can_priv *priv = netdev_priv(ndev);
- u16 ctlr;
- int err;
-
- err = clk_enable(priv->clk);
- if (err) {
- netdev_err(ndev, "clk_enable() failed, error %d\n", err);
- return err;
- }
-
- ctlr = readw(&priv->regs->ctlr);
- ctlr &= ~RCAR_CAN_CTLR_SLPM;
- writew(ctlr, &priv->regs->ctlr);
- ctlr &= ~RCAR_CAN_CTLR_CANM;
- writew(ctlr, &priv->regs->ctlr);
- priv->can.state = CAN_STATE_ERROR_ACTIVE;
-
- if (netif_running(ndev)) {
- netif_device_attach(ndev);
- netif_start_queue(ndev);
- }
- return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(rcar_can_pm_ops, rcar_can_suspend, rcar_can_resume);
-
-static const struct of_device_id rcar_can_of_table[] __maybe_unused = {
- { .compatible = "renesas,can-r8a7778" },
- { .compatible = "renesas,can-r8a7779" },
- { .compatible = "renesas,can-r8a7790" },
- { .compatible = "renesas,can-r8a7791" },
- { .compatible = "renesas,rcar-gen1-can" },
- { .compatible = "renesas,rcar-gen2-can" },
- { .compatible = "renesas,rcar-gen3-can" },
- { }
-};
-MODULE_DEVICE_TABLE(of, rcar_can_of_table);
-
-static struct platform_driver rcar_can_driver = {
- .driver = {
- .name = RCAR_CAN_DRV_NAME,
- .of_match_table = of_match_ptr(rcar_can_of_table),
- .pm = &rcar_can_pm_ops,
- },
- .probe = rcar_can_probe,
- .remove = rcar_can_remove,
-};
-
-module_platform_driver(rcar_can_driver);
-
-MODULE_AUTHOR("Cogent Embedded, Inc.");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("CAN driver for Renesas R-Car SoC");
-MODULE_ALIAS("platform:" RCAR_CAN_DRV_NAME);
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
deleted file mode 100644
index ba9dfc942..000000000
--- a/drivers/net/dsa/mv88e6xxx.c
+++ /dev/null
@@ -1,3723 +0,0 @@
-/*
- * net/dsa/mv88e6xxx.c - Marvell 88e6xxx switch chip support
- * Copyright (c) 2008 Marvell Semiconductor
- *
- * Copyright (c) 2015 CMC Electronics, Inc.
- * Added support for VLAN Table Unit operations
- *
- * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
- *
- * 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.
- */
-
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/if_bridge.h>
-#include <linux/jiffies.h>
-#include <linux/list.h>
-#include <linux/mdio.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/gpio/consumer.h>
-#include <linux/phy.h>
-#include <net/dsa.h>
-#include <net/switchdev.h>
-#include "mv88e6xxx.h"
-
-static void assert_smi_lock(struct mv88e6xxx_priv_state *ps)
-{
- if (unlikely(!mutex_is_locked(&ps->smi_mutex))) {
- dev_err(ps->dev, "SMI lock not held!\n");
- dump_stack();
- }
-}
-
-/* If the switch's ADDR[4:0] strap pins are strapped to zero, it will
- * use all 32 SMI bus addresses on its SMI bus, and all switch registers
- * will be directly accessible on some {device address,register address}
- * pair. If the ADDR[4:0] pins are not strapped to zero, the switch
- * will only respond to SMI transactions to that specific address, and
- * an indirect addressing mechanism needs to be used to access its
- * registers.
- */
-static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
-{
- int ret;
- int i;
-
- for (i = 0; i < 16; i++) {
- ret = mdiobus_read_nested(bus, sw_addr, SMI_CMD);
- if (ret < 0)
- return ret;
-
- if ((ret & SMI_CMD_BUSY) == 0)
- return 0;
- }
-
- return -ETIMEDOUT;
-}
-
-static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr,
- int reg)
-{
- int ret;
-
- if (sw_addr == 0)
- return mdiobus_read_nested(bus, addr, reg);
-
- /* Wait for the bus to become free. */
- ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
- if (ret < 0)
- return ret;
-
- /* Transmit the read command. */
- ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD,
- SMI_CMD_OP_22_READ | (addr << 5) | reg);
- if (ret < 0)
- return ret;
-
- /* Wait for the read command to complete. */
- ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
- if (ret < 0)
- return ret;
-
- /* Read the data. */
- ret = mdiobus_read_nested(bus, sw_addr, SMI_DATA);
- if (ret < 0)
- return ret;
-
- return ret & 0xffff;
-}
-
-static int _mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps,
- int addr, int reg)
-{
- int ret;
-
- assert_smi_lock(ps);
-
- ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg);
- if (ret < 0)
- return ret;
-
- dev_dbg(ps->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
- addr, reg, ret);
-
- return ret;
-}
-
-int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg)
-{
- int ret;
-
- mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_reg_read(ps, addr, reg);
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
-static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
- int reg, u16 val)
-{
- int ret;
-
- if (sw_addr == 0)
- return mdiobus_write_nested(bus, addr, reg, val);
-
- /* Wait for the bus to become free. */
- ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
- if (ret < 0)
- return ret;
-
- /* Transmit the data to write. */
- ret = mdiobus_write_nested(bus, sw_addr, SMI_DATA, val);
- if (ret < 0)
- return ret;
-
- /* Transmit the write command. */
- ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD,
- SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
- if (ret < 0)
- return ret;
-
- /* Wait for the write command to complete. */
- ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int _mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
- int reg, u16 val)
-{
- assert_smi_lock(ps);
-
- dev_dbg(ps->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
- addr, reg, val);
-
- return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val);
-}
-
-int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
- int reg, u16 val)
-{
- int ret;
-
- mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_reg_write(ps, addr, reg, val);
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
-static int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int err;
-
- err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_01,
- (addr[0] << 8) | addr[1]);
- if (err)
- return err;
-
- err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_23,
- (addr[2] << 8) | addr[3]);
- if (err)
- return err;
-
- return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_45,
- (addr[4] << 8) | addr[5]);
-}
-
-static int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
- int i;
-
- for (i = 0; i < 6; i++) {
- int j;
-
- /* Write the MAC address byte. */
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SWITCH_MAC,
- GLOBAL2_SWITCH_MAC_BUSY |
- (i << 8) | addr[i]);
- if (ret)
- return ret;
-
- /* Wait for the write to complete. */
- for (j = 0; j < 16; j++) {
- ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2,
- GLOBAL2_SWITCH_MAC);
- if (ret < 0)
- return ret;
-
- if ((ret & GLOBAL2_SWITCH_MAC_BUSY) == 0)
- break;
- }
- if (j == 16)
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SWITCH_MAC))
- return mv88e6xxx_set_addr_indirect(ds, addr);
- else
- return mv88e6xxx_set_addr_direct(ds, addr);
-}
-
-static int _mv88e6xxx_phy_read(struct mv88e6xxx_priv_state *ps, int addr,
- int regnum)
-{
- if (addr >= 0)
- return _mv88e6xxx_reg_read(ps, addr, regnum);
- return 0xffff;
-}
-
-static int _mv88e6xxx_phy_write(struct mv88e6xxx_priv_state *ps, int addr,
- int regnum, u16 val)
-{
- if (addr >= 0)
- return _mv88e6xxx_reg_write(ps, addr, regnum, val);
- return 0;
-}
-
-static int mv88e6xxx_ppu_disable(struct mv88e6xxx_priv_state *ps)
-{
- int ret;
- unsigned long timeout;
-
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
- ret & ~GLOBAL_CONTROL_PPU_ENABLE);
- if (ret)
- return ret;
-
- timeout = jiffies + 1 * HZ;
- while (time_before(jiffies, timeout)) {
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
- if (ret < 0)
- return ret;
-
- usleep_range(1000, 2000);
- if ((ret & GLOBAL_STATUS_PPU_MASK) !=
- GLOBAL_STATUS_PPU_POLLING)
- return 0;
- }
-
- return -ETIMEDOUT;
-}
-
-static int mv88e6xxx_ppu_enable(struct mv88e6xxx_priv_state *ps)
-{
- int ret, err;
- unsigned long timeout;
-
- ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
- if (ret < 0)
- return ret;
-
- err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
- ret | GLOBAL_CONTROL_PPU_ENABLE);
- if (err)
- return err;
-
- timeout = jiffies + 1 * HZ;
- while (time_before(jiffies, timeout)) {
- ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
- if (ret < 0)
- return ret;
-
- usleep_range(1000, 2000);
- if ((ret & GLOBAL_STATUS_PPU_MASK) ==
- GLOBAL_STATUS_PPU_POLLING)
- return 0;
- }
-
- return -ETIMEDOUT;
-}
-
-static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
-{
- struct mv88e6xxx_priv_state *ps;
-
- ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
- if (mutex_trylock(&ps->ppu_mutex)) {
- if (mv88e6xxx_ppu_enable(ps) == 0)
- ps->ppu_disabled = 0;
- mutex_unlock(&ps->ppu_mutex);
- }
-}
-
-static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
-{
- struct mv88e6xxx_priv_state *ps = (void *)_ps;
-
- schedule_work(&ps->ppu_work);
-}
-
-static int mv88e6xxx_ppu_access_get(struct mv88e6xxx_priv_state *ps)
-{
- int ret;
-
- mutex_lock(&ps->ppu_mutex);
-
- /* If the PHY polling unit is enabled, disable it so that
- * we can access the PHY registers. If it was already
- * disabled, cancel the timer that is going to re-enable
- * it.
- */
- if (!ps->ppu_disabled) {
- ret = mv88e6xxx_ppu_disable(ps);
- if (ret < 0) {
- mutex_unlock(&ps->ppu_mutex);
- return ret;
- }
- ps->ppu_disabled = 1;
- } else {
- del_timer(&ps->ppu_timer);
- ret = 0;
- }
-
- return ret;
-}
-
-static void mv88e6xxx_ppu_access_put(struct mv88e6xxx_priv_state *ps)
-{
- /* Schedule a timer to re-enable the PHY polling unit. */
- mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10));
- mutex_unlock(&ps->ppu_mutex);
-}
-
-void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
-{
- mutex_init(&ps->ppu_mutex);
- INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
- init_timer(&ps->ppu_timer);
- ps->ppu_timer.data = (unsigned long)ps;
- ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
-}
-
-static int mv88e6xxx_phy_read_ppu(struct mv88e6xxx_priv_state *ps, int addr,
- int regnum)
-{
- int ret;
-
- ret = mv88e6xxx_ppu_access_get(ps);
- if (ret >= 0) {
- ret = _mv88e6xxx_reg_read(ps, addr, regnum);
- mv88e6xxx_ppu_access_put(ps);
- }
-
- return ret;
-}
-
-static int mv88e6xxx_phy_write_ppu(struct mv88e6xxx_priv_state *ps, int addr,
- int regnum, u16 val)
-{
- int ret;
-
- ret = mv88e6xxx_ppu_access_get(ps);
- if (ret >= 0) {
- ret = _mv88e6xxx_reg_write(ps, addr, regnum, val);
- mv88e6xxx_ppu_access_put(ps);
- }
-
- return ret;
-}
-
-static bool mv88e6xxx_6065_family(struct mv88e6xxx_priv_state *ps)
-{
- return ps->info->family == MV88E6XXX_FAMILY_6065;
-}
-
-static bool mv88e6xxx_6095_family(struct mv88e6xxx_priv_state *ps)
-{
- return ps->info->family == MV88E6XXX_FAMILY_6095;
-}
-
-static bool mv88e6xxx_6097_family(struct mv88e6xxx_priv_state *ps)
-{
- return ps->info->family == MV88E6XXX_FAMILY_6097;
-}
-
-static bool mv88e6xxx_6165_family(struct mv88e6xxx_priv_state *ps)
-{
- return ps->info->family == MV88E6XXX_FAMILY_6165;
-}
-
-static bool mv88e6xxx_6185_family(struct mv88e6xxx_priv_state *ps)
-{
- return ps->info->family == MV88E6XXX_FAMILY_6185;
-}
-
-static bool mv88e6xxx_6320_family(struct mv88e6xxx_priv_state *ps)
-{
- return ps->info->family == MV88E6XXX_FAMILY_6320;
-}
-
-static bool mv88e6xxx_6351_family(struct mv88e6xxx_priv_state *ps)
-{
- return ps->info->family == MV88E6XXX_FAMILY_6351;
-}
-
-static bool mv88e6xxx_6352_family(struct mv88e6xxx_priv_state *ps)
-{
- return ps->info->family == MV88E6XXX_FAMILY_6352;
-}
-
-static unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_priv_state *ps)
-{
- return ps->info->num_databases;
-}
-
-static bool mv88e6xxx_has_fid_reg(struct mv88e6xxx_priv_state *ps)
-{
- /* Does the device have dedicated FID registers for ATU and VTU ops? */
- if (mv88e6xxx_6097_family(ps) || mv88e6xxx_6165_family(ps) ||
- mv88e6xxx_6351_family(ps) || mv88e6xxx_6352_family(ps))
- return true;
-
- return false;
-}
-
-/* We expect the switch to perform auto negotiation if there is a real
- * phy. However, in the case of a fixed link phy, we force the port
- * settings from the fixed link settings.
- */
-static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
- struct phy_device *phydev)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u32 reg;
- int ret;
-
- if (!phy_is_pseudo_fixed_link(phydev))
- return;
-
- mutex_lock(&ps->smi_mutex);
-
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_PCS_CTRL);
- if (ret < 0)
- goto out;
-
- reg = ret & ~(PORT_PCS_CTRL_LINK_UP |
- PORT_PCS_CTRL_FORCE_LINK |
- PORT_PCS_CTRL_DUPLEX_FULL |
- PORT_PCS_CTRL_FORCE_DUPLEX |
- PORT_PCS_CTRL_UNFORCED);
-
- reg |= PORT_PCS_CTRL_FORCE_LINK;
- if (phydev->link)
- reg |= PORT_PCS_CTRL_LINK_UP;
-
- if (mv88e6xxx_6065_family(ps) && phydev->speed > SPEED_100)
- goto out;
-
- switch (phydev->speed) {
- case SPEED_1000:
- reg |= PORT_PCS_CTRL_1000;
- break;
- case SPEED_100:
- reg |= PORT_PCS_CTRL_100;
- break;
- case SPEED_10:
- reg |= PORT_PCS_CTRL_10;
- break;
- default:
- pr_info("Unknown speed");
- goto out;
- }
-
- reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
- if (phydev->duplex == DUPLEX_FULL)
- reg |= PORT_PCS_CTRL_DUPLEX_FULL;
-
- if ((mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps)) &&
- (port >= ps->info->num_ports - 2)) {
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
- reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
- reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
- PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
- }
- _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_PCS_CTRL, reg);
-
-out:
- mutex_unlock(&ps->smi_mutex);
-}
-
-static int _mv88e6xxx_stats_wait(struct mv88e6xxx_priv_state *ps)
-{
- int ret;
- int i;
-
- for (i = 0; i < 10; i++) {
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATS_OP);
- if ((ret & GLOBAL_STATS_OP_BUSY) == 0)
- return 0;
- }
-
- return -ETIMEDOUT;
-}
-
-static int _mv88e6xxx_stats_snapshot(struct mv88e6xxx_priv_state *ps,
- int port)
-{
- int ret;
-
- if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps))
- port = (port + 1) << 5;
-
- /* Snapshot the hardware statistics counters for this port. */
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,
- GLOBAL_STATS_OP_CAPTURE_PORT |
- GLOBAL_STATS_OP_HIST_RX_TX | port);
- if (ret < 0)
- return ret;
-
- /* Wait for the snapshotting to complete. */
- ret = _mv88e6xxx_stats_wait(ps);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static void _mv88e6xxx_stats_read(struct mv88e6xxx_priv_state *ps,
- int stat, u32 *val)
-{
- u32 _val;
- int ret;
-
- *val = 0;
-
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,
- GLOBAL_STATS_OP_READ_CAPTURED |
- GLOBAL_STATS_OP_HIST_RX_TX | stat);
- if (ret < 0)
- return;
-
- ret = _mv88e6xxx_stats_wait(ps);
- if (ret < 0)
- return;
-
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATS_COUNTER_32);
- if (ret < 0)
- return;
-
- _val = ret << 16;
-
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATS_COUNTER_01);
- if (ret < 0)
- return;
-
- *val = _val | ret;
-}
-
-static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
- { "in_good_octets", 8, 0x00, BANK0, },
- { "in_bad_octets", 4, 0x02, BANK0, },
- { "in_unicast", 4, 0x04, BANK0, },
- { "in_broadcasts", 4, 0x06, BANK0, },
- { "in_multicasts", 4, 0x07, BANK0, },
- { "in_pause", 4, 0x16, BANK0, },
- { "in_undersize", 4, 0x18, BANK0, },
- { "in_fragments", 4, 0x19, BANK0, },
- { "in_oversize", 4, 0x1a, BANK0, },
- { "in_jabber", 4, 0x1b, BANK0, },
- { "in_rx_error", 4, 0x1c, BANK0, },
- { "in_fcs_error", 4, 0x1d, BANK0, },
- { "out_octets", 8, 0x0e, BANK0, },
- { "out_unicast", 4, 0x10, BANK0, },
- { "out_broadcasts", 4, 0x13, BANK0, },
- { "out_multicasts", 4, 0x12, BANK0, },
- { "out_pause", 4, 0x15, BANK0, },
- { "excessive", 4, 0x11, BANK0, },
- { "collisions", 4, 0x1e, BANK0, },
- { "deferred", 4, 0x05, BANK0, },
- { "single", 4, 0x14, BANK0, },
- { "multiple", 4, 0x17, BANK0, },
- { "out_fcs_error", 4, 0x03, BANK0, },
- { "late", 4, 0x1f, BANK0, },
- { "hist_64bytes", 4, 0x08, BANK0, },
- { "hist_65_127bytes", 4, 0x09, BANK0, },
- { "hist_128_255bytes", 4, 0x0a, BANK0, },
- { "hist_256_511bytes", 4, 0x0b, BANK0, },
- { "hist_512_1023bytes", 4, 0x0c, BANK0, },
- { "hist_1024_max_bytes", 4, 0x0d, BANK0, },
- { "sw_in_discards", 4, 0x10, PORT, },
- { "sw_in_filtered", 2, 0x12, PORT, },
- { "sw_out_filtered", 2, 0x13, PORT, },
- { "in_discards", 4, 0x00 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_filtered", 4, 0x01 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_accepted", 4, 0x02 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_bad_accepted", 4, 0x03 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_good_avb_class_a", 4, 0x04 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_good_avb_class_b", 4, 0x05 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_bad_avb_class_a", 4, 0x06 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_bad_avb_class_b", 4, 0x07 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_0", 4, 0x08 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_1", 4, 0x09 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_2", 4, 0x0a | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_3", 4, 0x0b | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_da_unknown", 4, 0x0e | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_management", 4, 0x0f | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_0", 4, 0x10 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_1", 4, 0x11 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_2", 4, 0x12 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_3", 4, 0x13 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_4", 4, 0x14 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_5", 4, 0x15 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_6", 4, 0x16 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_7", 4, 0x17 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_cut_through", 4, 0x18 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_octets_a", 4, 0x1a | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_octets_b", 4, 0x1b | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_management", 4, 0x1f | GLOBAL_STATS_OP_BANK_1, BANK1, },
-};
-
-static bool mv88e6xxx_has_stat(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_hw_stat *stat)
-{
- switch (stat->type) {
- case BANK0:
- return true;
- case BANK1:
- return mv88e6xxx_6320_family(ps);
- case PORT:
- return mv88e6xxx_6095_family(ps) ||
- mv88e6xxx_6185_family(ps) ||
- mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6165_family(ps) ||
- mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6352_family(ps);
- }
- return false;
-}
-
-static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_hw_stat *s,
- int port)
-{
- u32 low;
- u32 high = 0;
- int ret;
- u64 value;
-
- switch (s->type) {
- case PORT:
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), s->reg);
- if (ret < 0)
- return UINT64_MAX;
-
- low = ret;
- if (s->sizeof_stat == 4) {
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(port),
- s->reg + 1);
- if (ret < 0)
- return UINT64_MAX;
- high = ret;
- }
- break;
- case BANK0:
- case BANK1:
- _mv88e6xxx_stats_read(ps, s->reg, &low);
- if (s->sizeof_stat == 8)
- _mv88e6xxx_stats_read(ps, s->reg + 1, &high);
- }
- value = (((u64)high) << 16) | low;
- return value;
-}
-
-static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
- uint8_t *data)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct mv88e6xxx_hw_stat *stat;
- int i, j;
-
- for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
- stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(ps, stat)) {
- memcpy(data + j * ETH_GSTRING_LEN, stat->string,
- ETH_GSTRING_LEN);
- j++;
- }
- }
-}
-
-static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct mv88e6xxx_hw_stat *stat;
- int i, j;
-
- for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
- stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(ps, stat))
- j++;
- }
- return j;
-}
-
-static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
- uint64_t *data)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct mv88e6xxx_hw_stat *stat;
- int ret;
- int i, j;
-
- mutex_lock(&ps->smi_mutex);
-
- ret = _mv88e6xxx_stats_snapshot(ps, port);
- if (ret < 0) {
- mutex_unlock(&ps->smi_mutex);
- return;
- }
- for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
- stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(ps, stat)) {
- data[j] = _mv88e6xxx_get_ethtool_stat(ps, stat, port);
- j++;
- }
- }
-
- mutex_unlock(&ps->smi_mutex);
-}
-
-static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
-{
- return 32 * sizeof(u16);
-}
-
-static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
- struct ethtool_regs *regs, void *_p)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u16 *p = _p;
- int i;
-
- regs->version = 0;
-
- memset(p, 0xff, 32 * sizeof(u16));
-
- mutex_lock(&ps->smi_mutex);
-
- for (i = 0; i < 32; i++) {
- int ret;
-
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), i);
- if (ret >= 0)
- p[i] = ret;
- }
-
- mutex_unlock(&ps->smi_mutex);
-}
-
-static int _mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg, int offset,
- u16 mask)
-{
- unsigned long timeout = jiffies + HZ / 10;
-
- while (time_before(jiffies, timeout)) {
- int ret;
-
- ret = _mv88e6xxx_reg_read(ps, reg, offset);
- if (ret < 0)
- return ret;
- if (!(ret & mask))
- return 0;
-
- usleep_range(1000, 2000);
- }
- return -ETIMEDOUT;
-}
-
-static int mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg,
- int offset, u16 mask)
-{
- int ret;
-
- mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_wait(ps, reg, offset, mask);
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
-static int _mv88e6xxx_phy_wait(struct mv88e6xxx_priv_state *ps)
-{
- return _mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_SMI_OP,
- GLOBAL2_SMI_OP_BUSY);
-}
-
-static int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- return mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
- GLOBAL2_EEPROM_OP_LOAD);
-}
-
-static int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- return mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
- GLOBAL2_EEPROM_OP_BUSY);
-}
-
-static int mv88e6xxx_read_eeprom_word(struct dsa_switch *ds, int addr)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- mutex_lock(&ps->eeprom_mutex);
-
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
- GLOBAL2_EEPROM_OP_READ |
- (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
- if (ret < 0)
- goto error;
-
- ret = mv88e6xxx_eeprom_busy_wait(ds);
- if (ret < 0)
- goto error;
-
- ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
-error:
- mutex_unlock(&ps->eeprom_mutex);
- return ret;
-}
-
-static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
- return ps->eeprom_len;
-
- return 0;
-}
-
-static int mv88e6xxx_get_eeprom(struct dsa_switch *ds,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int offset;
- int len;
- int ret;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
- return -EOPNOTSUPP;
-
- offset = eeprom->offset;
- len = eeprom->len;
- eeprom->len = 0;
-
- eeprom->magic = 0xc3ec4951;
-
- ret = mv88e6xxx_eeprom_load_wait(ds);
- if (ret < 0)
- return ret;
-
- if (offset & 1) {
- int word;
-
- word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- *data++ = (word >> 8) & 0xff;
-
- offset++;
- len--;
- eeprom->len++;
- }
-
- while (len >= 2) {
- int word;
-
- word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- *data++ = word & 0xff;
- *data++ = (word >> 8) & 0xff;
-
- offset += 2;
- len -= 2;
- eeprom->len += 2;
- }
-
- if (len) {
- int word;
-
- word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- *data++ = word & 0xff;
-
- offset++;
- len--;
- eeprom->len++;
- }
-
- return 0;
-}
-
-static int mv88e6xxx_eeprom_is_readonly(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
- if (ret < 0)
- return ret;
-
- if (!(ret & GLOBAL2_EEPROM_OP_WRITE_EN))
- return -EROFS;
-
- return 0;
-}
-
-static int mv88e6xxx_write_eeprom_word(struct dsa_switch *ds, int addr,
- u16 data)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- mutex_lock(&ps->eeprom_mutex);
-
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
- if (ret < 0)
- goto error;
-
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
- GLOBAL2_EEPROM_OP_WRITE |
- (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
- if (ret < 0)
- goto error;
-
- ret = mv88e6xxx_eeprom_busy_wait(ds);
-error:
- mutex_unlock(&ps->eeprom_mutex);
- return ret;
-}
-
-static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int offset;
- int ret;
- int len;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
- return -EOPNOTSUPP;
-
- if (eeprom->magic != 0xc3ec4951)
- return -EINVAL;
-
- ret = mv88e6xxx_eeprom_is_readonly(ds);
- if (ret)
- return ret;
-
- offset = eeprom->offset;
- len = eeprom->len;
- eeprom->len = 0;
-
- ret = mv88e6xxx_eeprom_load_wait(ds);
- if (ret < 0)
- return ret;
-
- if (offset & 1) {
- int word;
-
- word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- word = (*data++ << 8) | (word & 0xff);
-
- ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
- if (ret < 0)
- return ret;
-
- offset++;
- len--;
- eeprom->len++;
- }
-
- while (len >= 2) {
- int word;
-
- word = *data++;
- word |= *data++ << 8;
-
- ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
- if (ret < 0)
- return ret;
-
- offset += 2;
- len -= 2;
- eeprom->len += 2;
- }
-
- if (len) {
- int word;
-
- word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- word = (word & 0xff00) | *data++;
-
- ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
- if (ret < 0)
- return ret;
-
- offset++;
- len--;
- eeprom->len++;
- }
-
- return 0;
-}
-
-static int _mv88e6xxx_atu_wait(struct mv88e6xxx_priv_state *ps)
-{
- return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_ATU_OP,
- GLOBAL_ATU_OP_BUSY);
-}
-
-static int _mv88e6xxx_phy_read_indirect(struct mv88e6xxx_priv_state *ps,
- int addr, int regnum)
-{
- int ret;
-
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SMI_OP,
- GLOBAL2_SMI_OP_22_READ | (addr << 5) |
- regnum);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_phy_wait(ps);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_SMI_DATA);
-
- return ret;
-}
-
-static int _mv88e6xxx_phy_write_indirect(struct mv88e6xxx_priv_state *ps,
- int addr, int regnum, u16 val)
-{
- int ret;
-
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SMI_DATA, val);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SMI_OP,
- GLOBAL2_SMI_OP_22_WRITE | (addr << 5) |
- regnum);
-
- return _mv88e6xxx_phy_wait(ps);
-}
-
-static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
- struct ethtool_eee *e)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int reg;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
- return -EOPNOTSUPP;
-
- mutex_lock(&ps->smi_mutex);
-
- reg = _mv88e6xxx_phy_read_indirect(ps, port, 16);
- if (reg < 0)
- goto out;
-
- e->eee_enabled = !!(reg & 0x0200);
- e->tx_lpi_enabled = !!(reg & 0x0100);
-
- reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_STATUS);
- if (reg < 0)
- goto out;
-
- e->eee_active = !!(reg & PORT_STATUS_EEE);
- reg = 0;
-
-out:
- mutex_unlock(&ps->smi_mutex);
- return reg;
-}
-
-static int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
- struct phy_device *phydev, struct ethtool_eee *e)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int reg;
- int ret;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
- return -EOPNOTSUPP;
-
- mutex_lock(&ps->smi_mutex);
-
- ret = _mv88e6xxx_phy_read_indirect(ps, port, 16);
- if (ret < 0)
- goto out;
-
- reg = ret & ~0x0300;
- if (e->eee_enabled)
- reg |= 0x0200;
- if (e->tx_lpi_enabled)
- reg |= 0x0100;
-
- ret = _mv88e6xxx_phy_write_indirect(ps, port, 16, reg);
-out:
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
-static int _mv88e6xxx_atu_cmd(struct mv88e6xxx_priv_state *ps, u16 fid, u16 cmd)
-{
- int ret;
-
- if (mv88e6xxx_has_fid_reg(ps)) {
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_FID, fid);
- if (ret < 0)
- return ret;
- } else if (mv88e6xxx_num_databases(ps) == 256) {
- /* ATU DBNum[7:4] are located in ATU Control 15:12 */
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL,
- (ret & 0xfff) |
- ((fid << 8) & 0xf000));
- if (ret < 0)
- return ret;
-
- /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
- cmd |= fid & 0xf;
- }
-
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_OP, cmd);
- if (ret < 0)
- return ret;
-
- return _mv88e6xxx_atu_wait(ps);
-}
-
-static int _mv88e6xxx_atu_data_write(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_atu_entry *entry)
-{
- u16 data = entry->state & GLOBAL_ATU_DATA_STATE_MASK;
-
- if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) {
- unsigned int mask, shift;
-
- if (entry->trunk) {
- data |= GLOBAL_ATU_DATA_TRUNK;
- mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK;
- shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT;
- } else {
- mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK;
- shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT;
- }
-
- data |= (entry->portv_trunkid << shift) & mask;
- }
-
- return _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_DATA, data);
-}
-
-static int _mv88e6xxx_atu_flush_move(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_atu_entry *entry,
- bool static_too)
-{
- int op;
- int err;
-
- err = _mv88e6xxx_atu_wait(ps);
- if (err)
- return err;
-
- err = _mv88e6xxx_atu_data_write(ps, entry);
- if (err)
- return err;
-
- if (entry->fid) {
- op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB :
- GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB;
- } else {
- op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL :
- GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC;
- }
-
- return _mv88e6xxx_atu_cmd(ps, entry->fid, op);
-}
-
-static int _mv88e6xxx_atu_flush(struct mv88e6xxx_priv_state *ps,
- u16 fid, bool static_too)
-{
- struct mv88e6xxx_atu_entry entry = {
- .fid = fid,
- .state = 0, /* EntryState bits must be 0 */
- };
-
- return _mv88e6xxx_atu_flush_move(ps, &entry, static_too);
-}
-
-static int _mv88e6xxx_atu_move(struct mv88e6xxx_priv_state *ps, u16 fid,
- int from_port, int to_port, bool static_too)
-{
- struct mv88e6xxx_atu_entry entry = {
- .trunk = false,
- .fid = fid,
- };
-
- /* EntryState bits must be 0xF */
- entry.state = GLOBAL_ATU_DATA_STATE_MASK;
-
- /* ToPort and FromPort are respectively in PortVec bits 7:4 and 3:0 */
- entry.portv_trunkid = (to_port & 0x0f) << 4;
- entry.portv_trunkid |= from_port & 0x0f;
-
- return _mv88e6xxx_atu_flush_move(ps, &entry, static_too);
-}
-
-static int _mv88e6xxx_atu_remove(struct mv88e6xxx_priv_state *ps, u16 fid,
- int port, bool static_too)
-{
- /* Destination port 0xF means remove the entries */
- return _mv88e6xxx_atu_move(ps, fid, port, 0x0f, static_too);
-}
-
-static const char * const mv88e6xxx_port_state_names[] = {
- [PORT_CONTROL_STATE_DISABLED] = "Disabled",
- [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening",
- [PORT_CONTROL_STATE_LEARNING] = "Learning",
- [PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
-};
-
-static int _mv88e6xxx_port_state(struct mv88e6xxx_priv_state *ps, int port,
- u8 state)
-{
- struct dsa_switch *ds = ps->ds;
- int reg, ret = 0;
- u8 oldstate;
-
- reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL);
- if (reg < 0)
- return reg;
-
- oldstate = reg & PORT_CONTROL_STATE_MASK;
-
- if (oldstate != state) {
- /* Flush forwarding database if we're moving a port
- * from Learning or Forwarding state to Disabled or
- * Blocking or Listening state.
- */
- if ((oldstate == PORT_CONTROL_STATE_LEARNING ||
- oldstate == PORT_CONTROL_STATE_FORWARDING)
- && (state == PORT_CONTROL_STATE_DISABLED ||
- state == PORT_CONTROL_STATE_BLOCKING)) {
- ret = _mv88e6xxx_atu_remove(ps, 0, port, false);
- if (ret)
- return ret;
- }
-
- reg = (reg & ~PORT_CONTROL_STATE_MASK) | state;
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL,
- reg);
- if (ret)
- return ret;
-
- netdev_dbg(ds->ports[port], "PortState %s (was %s)\n",
- mv88e6xxx_port_state_names[state],
- mv88e6xxx_port_state_names[oldstate]);
- }
-
- return ret;
-}
-
-static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_priv_state *ps,
- int port)
-{
- struct net_device *bridge = ps->ports[port].bridge_dev;
- const u16 mask = (1 << ps->info->num_ports) - 1;
- struct dsa_switch *ds = ps->ds;
- u16 output_ports = 0;
- int reg;
- int i;
-
- /* allow CPU port or DSA link(s) to send frames to every port */
- if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
- output_ports = mask;
- } else {
- for (i = 0; i < ps->info->num_ports; ++i) {
- /* allow sending frames to every group member */
- if (bridge && ps->ports[i].bridge_dev == bridge)
- output_ports |= BIT(i);
-
- /* allow sending frames to CPU port and DSA link(s) */
- if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
- output_ports |= BIT(i);
- }
- }
-
- /* prevent frames from going back out of the port they came in on */
- output_ports &= ~BIT(port);
-
- reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_BASE_VLAN);
- if (reg < 0)
- return reg;
-
- reg &= ~mask;
- reg |= output_ports & mask;
-
- return _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_BASE_VLAN, reg);
-}
-
-static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
- u8 state)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int stp_state;
- int err;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_PORTSTATE))
- return;
-
- switch (state) {
- case BR_STATE_DISABLED:
- stp_state = PORT_CONTROL_STATE_DISABLED;
- break;
- case BR_STATE_BLOCKING:
- case BR_STATE_LISTENING:
- stp_state = PORT_CONTROL_STATE_BLOCKING;
- break;
- case BR_STATE_LEARNING:
- stp_state = PORT_CONTROL_STATE_LEARNING;
- break;
- case BR_STATE_FORWARDING:
- default:
- stp_state = PORT_CONTROL_STATE_FORWARDING;
- break;
- }
-
- mutex_lock(&ps->smi_mutex);
- err = _mv88e6xxx_port_state(ps, port, stp_state);
- mutex_unlock(&ps->smi_mutex);
-
- if (err)
- netdev_err(ds->ports[port], "failed to update state to %s\n",
- mv88e6xxx_port_state_names[stp_state]);
-}
-
-static int _mv88e6xxx_port_pvid(struct mv88e6xxx_priv_state *ps, int port,
- u16 *new, u16 *old)
-{
- struct dsa_switch *ds = ps->ds;
- u16 pvid;
- int ret;
-
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_DEFAULT_VLAN);
- if (ret < 0)
- return ret;
-
- pvid = ret & PORT_DEFAULT_VLAN_MASK;
-
- if (new) {
- ret &= ~PORT_DEFAULT_VLAN_MASK;
- ret |= *new & PORT_DEFAULT_VLAN_MASK;
-
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_DEFAULT_VLAN, ret);
- if (ret < 0)
- return ret;
-
- netdev_dbg(ds->ports[port], "DefaultVID %d (was %d)\n", *new,
- pvid);
- }
-
- if (old)
- *old = pvid;
-
- return 0;
-}
-
-static int _mv88e6xxx_port_pvid_get(struct mv88e6xxx_priv_state *ps,
- int port, u16 *pvid)
-{
- return _mv88e6xxx_port_pvid(ps, port, NULL, pvid);
-}
-
-static int _mv88e6xxx_port_pvid_set(struct mv88e6xxx_priv_state *ps,
- int port, u16 pvid)
-{
- return _mv88e6xxx_port_pvid(ps, port, &pvid, NULL);
-}
-
-static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_priv_state *ps)
-{
- return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_VTU_OP,
- GLOBAL_VTU_OP_BUSY);
-}
-
-static int _mv88e6xxx_vtu_cmd(struct mv88e6xxx_priv_state *ps, u16 op)
-{
- int ret;
-
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_OP, op);
- if (ret < 0)
- return ret;
-
- return _mv88e6xxx_vtu_wait(ps);
-}
-
-static int _mv88e6xxx_vtu_stu_flush(struct mv88e6xxx_priv_state *ps)
-{
- int ret;
-
- ret = _mv88e6xxx_vtu_wait(ps);
- if (ret < 0)
- return ret;
-
- return _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_FLUSH_ALL);
-}
-
-static int _mv88e6xxx_vtu_stu_data_read(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_vtu_stu_entry *entry,
- unsigned int nibble_offset)
-{
- u16 regs[3];
- int i;
- int ret;
-
- for (i = 0; i < 3; ++i) {
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
- GLOBAL_VTU_DATA_0_3 + i);
- if (ret < 0)
- return ret;
-
- regs[i] = ret;
- }
-
- for (i = 0; i < ps->info->num_ports; ++i) {
- unsigned int shift = (i % 4) * 4 + nibble_offset;
- u16 reg = regs[i / 4];
-
- entry->data[i] = (reg >> shift) & GLOBAL_VTU_STU_DATA_MASK;
- }
-
- return 0;
-}
-
-static int mv88e6xxx_vtu_data_read(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_vtu_stu_entry *entry)
-{
- return _mv88e6xxx_vtu_stu_data_read(ps, entry, 0);
-}
-
-static int mv88e6xxx_stu_data_read(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_vtu_stu_entry *entry)
-{
- return _mv88e6xxx_vtu_stu_data_read(ps, entry, 2);
-}
-
-static int _mv88e6xxx_vtu_stu_data_write(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_vtu_stu_entry *entry,
- unsigned int nibble_offset)
-{
- u16 regs[3] = { 0 };
- int i;
- int ret;
-
- for (i = 0; i < ps->info->num_ports; ++i) {
- unsigned int shift = (i % 4) * 4 + nibble_offset;
- u8 data = entry->data[i];
-
- regs[i / 4] |= (data & GLOBAL_VTU_STU_DATA_MASK) << shift;
- }
-
- for (i = 0; i < 3; ++i) {
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL,
- GLOBAL_VTU_DATA_0_3 + i, regs[i]);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-static int mv88e6xxx_vtu_data_write(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_vtu_stu_entry *entry)
-{
- return _mv88e6xxx_vtu_stu_data_write(ps, entry, 0);
-}
-
-static int mv88e6xxx_stu_data_write(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_vtu_stu_entry *entry)
-{
- return _mv88e6xxx_vtu_stu_data_write(ps, entry, 2);
-}
-
-static int _mv88e6xxx_vtu_vid_write(struct mv88e6xxx_priv_state *ps, u16 vid)
-{
- return _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_VID,
- vid & GLOBAL_VTU_VID_MASK);
-}
-
-static int _mv88e6xxx_vtu_getnext(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_vtu_stu_entry *entry)
-{
- struct mv88e6xxx_vtu_stu_entry next = { 0 };
- int ret;
-
- ret = _mv88e6xxx_vtu_wait(ps);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_VTU_GET_NEXT);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_VID);
- if (ret < 0)
- return ret;
-
- next.vid = ret & GLOBAL_VTU_VID_MASK;
- next.valid = !!(ret & GLOBAL_VTU_VID_VALID);
-
- if (next.valid) {
- ret = mv88e6xxx_vtu_data_read(ps, &next);
- if (ret < 0)
- return ret;
-
- if (mv88e6xxx_has_fid_reg(ps)) {
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
- GLOBAL_VTU_FID);
- if (ret < 0)
- return ret;
-
- next.fid = ret & GLOBAL_VTU_FID_MASK;
- } else if (mv88e6xxx_num_databases(ps) == 256) {
- /* VTU DBNum[7:4] are located in VTU Operation 11:8, and
- * VTU DBNum[3:0] are located in VTU Operation 3:0
- */
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
- GLOBAL_VTU_OP);
- if (ret < 0)
- return ret;
-
- next.fid = (ret & 0xf00) >> 4;
- next.fid |= ret & 0xf;
- }
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_STU)) {
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
- GLOBAL_VTU_SID);
- if (ret < 0)
- return ret;
-
- next.sid = ret & GLOBAL_VTU_SID_MASK;
- }
- }
-
- *entry = next;
- return 0;
-}
-
-static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
- struct switchdev_obj_port_vlan *vlan,
- int (*cb)(struct switchdev_obj *obj))
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct mv88e6xxx_vtu_stu_entry next;
- u16 pvid;
- int err;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
- return -EOPNOTSUPP;
-
- mutex_lock(&ps->smi_mutex);
-
- err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
- if (err)
- goto unlock;
-
- err = _mv88e6xxx_vtu_vid_write(ps, GLOBAL_VTU_VID_MASK);
- if (err)
- goto unlock;
-
- do {
- err = _mv88e6xxx_vtu_getnext(ps, &next);
- if (err)
- break;
-
- if (!next.valid)
- break;
-
- if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
- continue;
-
- /* reinit and dump this VLAN obj */
- vlan->vid_begin = vlan->vid_end = next.vid;
- vlan->flags = 0;
-
- if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED)
- vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
-
- if (next.vid == pvid)
- vlan->flags |= BRIDGE_VLAN_INFO_PVID;
-
- err = cb(&vlan->obj);
- if (err)
- break;
- } while (next.vid < GLOBAL_VTU_VID_MASK);
-
-unlock:
- mutex_unlock(&ps->smi_mutex);
-
- return err;
-}
-
-static int _mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_vtu_stu_entry *entry)
-{
- u16 op = GLOBAL_VTU_OP_VTU_LOAD_PURGE;
- u16 reg = 0;
- int ret;
-
- ret = _mv88e6xxx_vtu_wait(ps);
- if (ret < 0)
- return ret;
-
- if (!entry->valid)
- goto loadpurge;
-
- /* Write port member tags */
- ret = mv88e6xxx_vtu_data_write(ps, entry);
- if (ret < 0)
- return ret;
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_STU)) {
- reg = entry->sid & GLOBAL_VTU_SID_MASK;
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_SID, reg);
- if (ret < 0)
- return ret;
- }
-
- if (mv88e6xxx_has_fid_reg(ps)) {
- reg = entry->fid & GLOBAL_VTU_FID_MASK;
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_FID, reg);
- if (ret < 0)
- return ret;
- } else if (mv88e6xxx_num_databases(ps) == 256) {
- /* VTU DBNum[7:4] are located in VTU Operation 11:8, and
- * VTU DBNum[3:0] are located in VTU Operation 3:0
- */
- op |= (entry->fid & 0xf0) << 8;
- op |= entry->fid & 0xf;
- }
-
- reg = GLOBAL_VTU_VID_VALID;
-loadpurge:
- reg |= entry->vid & GLOBAL_VTU_VID_MASK;
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_VID, reg);
- if (ret < 0)
- return ret;
-
- return _mv88e6xxx_vtu_cmd(ps, op);
-}
-
-static int _mv88e6xxx_stu_getnext(struct mv88e6xxx_priv_state *ps, u8 sid,
- struct mv88e6xxx_vtu_stu_entry *entry)
-{
- struct mv88e6xxx_vtu_stu_entry next = { 0 };
- int ret;
-
- ret = _mv88e6xxx_vtu_wait(ps);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_SID,
- sid & GLOBAL_VTU_SID_MASK);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_STU_GET_NEXT);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_SID);
- if (ret < 0)
- return ret;
-
- next.sid = ret & GLOBAL_VTU_SID_MASK;
-
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_VID);
- if (ret < 0)
- return ret;
-
- next.valid = !!(ret & GLOBAL_VTU_VID_VALID);
-
- if (next.valid) {
- ret = mv88e6xxx_stu_data_read(ps, &next);
- if (ret < 0)
- return ret;
- }
-
- *entry = next;
- return 0;
-}
-
-static int _mv88e6xxx_stu_loadpurge(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_vtu_stu_entry *entry)
-{
- u16 reg = 0;
- int ret;
-
- ret = _mv88e6xxx_vtu_wait(ps);
- if (ret < 0)
- return ret;
-
- if (!entry->valid)
- goto loadpurge;
-
- /* Write port states */
- ret = mv88e6xxx_stu_data_write(ps, entry);
- if (ret < 0)
- return ret;
-
- reg = GLOBAL_VTU_VID_VALID;
-loadpurge:
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_VID, reg);
- if (ret < 0)
- return ret;
-
- reg = entry->sid & GLOBAL_VTU_SID_MASK;
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_SID, reg);
- if (ret < 0)
- return ret;
-
- return _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_STU_LOAD_PURGE);
-}
-
-static int _mv88e6xxx_port_fid(struct mv88e6xxx_priv_state *ps, int port,
- u16 *new, u16 *old)
-{
- struct dsa_switch *ds = ps->ds;
- u16 upper_mask;
- u16 fid;
- int ret;
-
- if (mv88e6xxx_num_databases(ps) == 4096)
- upper_mask = 0xff;
- else if (mv88e6xxx_num_databases(ps) == 256)
- upper_mask = 0xf;
- else
- return -EOPNOTSUPP;
-
- /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_BASE_VLAN);
- if (ret < 0)
- return ret;
-
- fid = (ret & PORT_BASE_VLAN_FID_3_0_MASK) >> 12;
-
- if (new) {
- ret &= ~PORT_BASE_VLAN_FID_3_0_MASK;
- ret |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK;
-
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_BASE_VLAN,
- ret);
- if (ret < 0)
- return ret;
- }
-
- /* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_1);
- if (ret < 0)
- return ret;
-
- fid |= (ret & upper_mask) << 4;
-
- if (new) {
- ret &= ~upper_mask;
- ret |= (*new >> 4) & upper_mask;
-
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1,
- ret);
- if (ret < 0)
- return ret;
-
- netdev_dbg(ds->ports[port], "FID %d (was %d)\n", *new, fid);
- }
-
- if (old)
- *old = fid;
-
- return 0;
-}
-
-static int _mv88e6xxx_port_fid_get(struct mv88e6xxx_priv_state *ps,
- int port, u16 *fid)
-{
- return _mv88e6xxx_port_fid(ps, port, NULL, fid);
-}
-
-static int _mv88e6xxx_port_fid_set(struct mv88e6xxx_priv_state *ps,
- int port, u16 fid)
-{
- return _mv88e6xxx_port_fid(ps, port, &fid, NULL);
-}
-
-static int _mv88e6xxx_fid_new(struct mv88e6xxx_priv_state *ps, u16 *fid)
-{
- DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
- struct mv88e6xxx_vtu_stu_entry vlan;
- int i, err;
-
- bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
-
- /* Set every FID bit used by the (un)bridged ports */
- for (i = 0; i < ps->info->num_ports; ++i) {
- err = _mv88e6xxx_port_fid_get(ps, i, fid);
- if (err)
- return err;
-
- set_bit(*fid, fid_bitmap);
- }
-
- /* Set every FID bit used by the VLAN entries */
- err = _mv88e6xxx_vtu_vid_write(ps, GLOBAL_VTU_VID_MASK);
- if (err)
- return err;
-
- do {
- err = _mv88e6xxx_vtu_getnext(ps, &vlan);
- if (err)
- return err;
-
- if (!vlan.valid)
- break;
-
- set_bit(vlan.fid, fid_bitmap);
- } while (vlan.vid < GLOBAL_VTU_VID_MASK);
-
- /* The reset value 0x000 is used to indicate that multiple address
- * databases are not needed. Return the next positive available.
- */
- *fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1);
- if (unlikely(*fid >= mv88e6xxx_num_databases(ps)))
- return -ENOSPC;
-
- /* Clear the database */
- return _mv88e6xxx_atu_flush(ps, *fid, true);
-}
-
-static int _mv88e6xxx_vtu_new(struct mv88e6xxx_priv_state *ps, u16 vid,
- struct mv88e6xxx_vtu_stu_entry *entry)
-{
- struct dsa_switch *ds = ps->ds;
- struct mv88e6xxx_vtu_stu_entry vlan = {
- .valid = true,
- .vid = vid,
- };
- int i, err;
-
- err = _mv88e6xxx_fid_new(ps, &vlan.fid);
- if (err)
- return err;
-
- /* exclude all ports except the CPU and DSA ports */
- for (i = 0; i < ps->info->num_ports; ++i)
- vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)
- ? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED
- : GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
-
- if (mv88e6xxx_6097_family(ps) || mv88e6xxx_6165_family(ps) ||
- mv88e6xxx_6351_family(ps) || mv88e6xxx_6352_family(ps)) {
- struct mv88e6xxx_vtu_stu_entry vstp;
-
- /* Adding a VTU entry requires a valid STU entry. As VSTP is not
- * implemented, only one STU entry is needed to cover all VTU
- * entries. Thus, validate the SID 0.
- */
- vlan.sid = 0;
- err = _mv88e6xxx_stu_getnext(ps, GLOBAL_VTU_SID_MASK, &vstp);
- if (err)
- return err;
-
- if (vstp.sid != vlan.sid || !vstp.valid) {
- memset(&vstp, 0, sizeof(vstp));
- vstp.valid = true;
- vstp.sid = vlan.sid;
-
- err = _mv88e6xxx_stu_loadpurge(ps, &vstp);
- if (err)
- return err;
- }
- }
-
- *entry = vlan;
- return 0;
-}
-
-static int _mv88e6xxx_vtu_get(struct mv88e6xxx_priv_state *ps, u16 vid,
- struct mv88e6xxx_vtu_stu_entry *entry, bool creat)
-{
- int err;
-
- if (!vid)
- return -EINVAL;
-
- err = _mv88e6xxx_vtu_vid_write(ps, vid - 1);
- if (err)
- return err;
-
- err = _mv88e6xxx_vtu_getnext(ps, entry);
- if (err)
- return err;
-
- if (entry->vid != vid || !entry->valid) {
- if (!creat)
- return -EOPNOTSUPP;
- /* -ENOENT would've been more appropriate, but switchdev expects
- * -EOPNOTSUPP to inform bridge about an eventual software VLAN.
- */
-
- err = _mv88e6xxx_vtu_new(ps, vid, entry);
- }
-
- return err;
-}
-
-static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
- u16 vid_begin, u16 vid_end)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct mv88e6xxx_vtu_stu_entry vlan;
- int i, err;
-
- if (!vid_begin)
- return -EOPNOTSUPP;
-
- mutex_lock(&ps->smi_mutex);
-
- err = _mv88e6xxx_vtu_vid_write(ps, vid_begin - 1);
- if (err)
- goto unlock;
-
- do {
- err = _mv88e6xxx_vtu_getnext(ps, &vlan);
- if (err)
- goto unlock;
-
- if (!vlan.valid)
- break;
-
- if (vlan.vid > vid_end)
- break;
-
- for (i = 0; i < ps->info->num_ports; ++i) {
- if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
- continue;
-
- if (vlan.data[i] ==
- GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
- continue;
-
- if (ps->ports[i].bridge_dev ==
- ps->ports[port].bridge_dev)
- break; /* same bridge, check next VLAN */
-
- netdev_warn(ds->ports[port],
- "hardware VLAN %d already used by %s\n",
- vlan.vid,
- netdev_name(ps->ports[i].bridge_dev));
- err = -EOPNOTSUPP;
- goto unlock;
- }
- } while (vlan.vid < vid_end);
-
-unlock:
- mutex_unlock(&ps->smi_mutex);
-
- return err;
-}
-
-static const char * const mv88e6xxx_port_8021q_mode_names[] = {
- [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
- [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
- [PORT_CONTROL_2_8021Q_CHECK] = "Check",
- [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
-};
-
-static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
- bool vlan_filtering)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
- PORT_CONTROL_2_8021Q_DISABLED;
- int ret;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
- return -EOPNOTSUPP;
-
- mutex_lock(&ps->smi_mutex);
-
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_2);
- if (ret < 0)
- goto unlock;
-
- old = ret & PORT_CONTROL_2_8021Q_MASK;
-
- if (new != old) {
- ret &= ~PORT_CONTROL_2_8021Q_MASK;
- ret |= new & PORT_CONTROL_2_8021Q_MASK;
-
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_2,
- ret);
- if (ret < 0)
- goto unlock;
-
- netdev_dbg(ds->ports[port], "802.1Q Mode %s (was %s)\n",
- mv88e6xxx_port_8021q_mode_names[new],
- mv88e6xxx_port_8021q_mode_names[old]);
- }
-
- ret = 0;
-unlock:
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
-static int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_vlan *vlan,
- struct switchdev_trans *trans)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int err;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
- return -EOPNOTSUPP;
-
- /* If the requested port doesn't belong to the same bridge as the VLAN
- * members, do not support it (yet) and fallback to software VLAN.
- */
- err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid_begin,
- vlan->vid_end);
- if (err)
- return err;
-
- /* We don't need any dynamic resource from the kernel (yet),
- * so skip the prepare phase.
- */
- return 0;
-}
-
-static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_priv_state *ps, int port,
- u16 vid, bool untagged)
-{
- struct mv88e6xxx_vtu_stu_entry vlan;
- int err;
-
- err = _mv88e6xxx_vtu_get(ps, vid, &vlan, true);
- if (err)
- return err;
-
- vlan.data[port] = untagged ?
- GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED :
- GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
-
- return _mv88e6xxx_vtu_loadpurge(ps, &vlan);
-}
-
-static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_vlan *vlan,
- struct switchdev_trans *trans)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
- bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
- u16 vid;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
- return;
-
- mutex_lock(&ps->smi_mutex);
-
- for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
- if (_mv88e6xxx_port_vlan_add(ps, port, vid, untagged))
- netdev_err(ds->ports[port], "failed to add VLAN %d%c\n",
- vid, untagged ? 'u' : 't');
-
- if (pvid && _mv88e6xxx_port_pvid_set(ps, port, vlan->vid_end))
- netdev_err(ds->ports[port], "failed to set PVID %d\n",
- vlan->vid_end);
-
- mutex_unlock(&ps->smi_mutex);
-}
-
-static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_priv_state *ps,
- int port, u16 vid)
-{
- struct dsa_switch *ds = ps->ds;
- struct mv88e6xxx_vtu_stu_entry vlan;
- int i, err;
-
- err = _mv88e6xxx_vtu_get(ps, vid, &vlan, false);
- if (err)
- return err;
-
- /* Tell switchdev if this VLAN is handled in software */
- if (vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
- return -EOPNOTSUPP;
-
- vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
-
- /* keep the VLAN unless all ports are excluded */
- vlan.valid = false;
- for (i = 0; i < ps->info->num_ports; ++i) {
- if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
- continue;
-
- if (vlan.data[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
- vlan.valid = true;
- break;
- }
- }
-
- err = _mv88e6xxx_vtu_loadpurge(ps, &vlan);
- if (err)
- return err;
-
- return _mv88e6xxx_atu_remove(ps, vlan.fid, port, false);
-}
-
-static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_vlan *vlan)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u16 pvid, vid;
- int err = 0;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
- return -EOPNOTSUPP;
-
- mutex_lock(&ps->smi_mutex);
-
- err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
- if (err)
- goto unlock;
-
- for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
- err = _mv88e6xxx_port_vlan_del(ps, port, vid);
- if (err)
- goto unlock;
-
- if (vid == pvid) {
- err = _mv88e6xxx_port_pvid_set(ps, port, 0);
- if (err)
- goto unlock;
- }
- }
-
-unlock:
- mutex_unlock(&ps->smi_mutex);
-
- return err;
-}
-
-static int _mv88e6xxx_atu_mac_write(struct mv88e6xxx_priv_state *ps,
- const unsigned char *addr)
-{
- int i, ret;
-
- for (i = 0; i < 3; i++) {
- ret = _mv88e6xxx_reg_write(
- ps, REG_GLOBAL, GLOBAL_ATU_MAC_01 + i,
- (addr[i * 2] << 8) | addr[i * 2 + 1]);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-static int _mv88e6xxx_atu_mac_read(struct mv88e6xxx_priv_state *ps,
- unsigned char *addr)
-{
- int i, ret;
-
- for (i = 0; i < 3; i++) {
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL,
- GLOBAL_ATU_MAC_01 + i);
- if (ret < 0)
- return ret;
- addr[i * 2] = ret >> 8;
- addr[i * 2 + 1] = ret & 0xff;
- }
-
- return 0;
-}
-
-static int _mv88e6xxx_atu_load(struct mv88e6xxx_priv_state *ps,
- struct mv88e6xxx_atu_entry *entry)
-{
- int ret;
-
- ret = _mv88e6xxx_atu_wait(ps);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_atu_mac_write(ps, entry->mac);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_atu_data_write(ps, entry);
- if (ret < 0)
- return ret;
-
- return _mv88e6xxx_atu_cmd(ps, entry->fid, GLOBAL_ATU_OP_LOAD_DB);
-}
-
-static int _mv88e6xxx_port_fdb_load(struct mv88e6xxx_priv_state *ps, int port,
- const unsigned char *addr, u16 vid,
- u8 state)
-{
- struct mv88e6xxx_atu_entry entry = { 0 };
- struct mv88e6xxx_vtu_stu_entry vlan;
- int err;
-
- /* Null VLAN ID corresponds to the port private database */
- if (vid == 0)
- err = _mv88e6xxx_port_fid_get(ps, port, &vlan.fid);
- else
- err = _mv88e6xxx_vtu_get(ps, vid, &vlan, false);
- if (err)
- return err;
-
- entry.fid = vlan.fid;
- entry.state = state;
- ether_addr_copy(entry.mac, addr);
- if (state != GLOBAL_ATU_DATA_STATE_UNUSED) {
- entry.trunk = false;
- entry.portv_trunkid = BIT(port);
- }
-
- return _mv88e6xxx_atu_load(ps, &entry);
-}
-
-static int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_fdb *fdb,
- struct switchdev_trans *trans)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
- return -EOPNOTSUPP;
-
- /* We don't need any dynamic resource from the kernel (yet),
- * so skip the prepare phase.
- */
- return 0;
-}
-
-static void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_fdb *fdb,
- struct switchdev_trans *trans)
-{
- int state = is_multicast_ether_addr(fdb->addr) ?
- GLOBAL_ATU_DATA_STATE_MC_STATIC :
- GLOBAL_ATU_DATA_STATE_UC_STATIC;
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
- return;
-
- mutex_lock(&ps->smi_mutex);
- if (_mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid, state))
- netdev_err(ds->ports[port], "failed to load MAC address\n");
- mutex_unlock(&ps->smi_mutex);
-}
-
-static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_fdb *fdb)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
- return -EOPNOTSUPP;
-
- mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid,
- GLOBAL_ATU_DATA_STATE_UNUSED);
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
-static int _mv88e6xxx_atu_getnext(struct mv88e6xxx_priv_state *ps, u16 fid,
- struct mv88e6xxx_atu_entry *entry)
-{
- struct mv88e6xxx_atu_entry next = { 0 };
- int ret;
-
- next.fid = fid;
-
- ret = _mv88e6xxx_atu_wait(ps);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_atu_cmd(ps, fid, GLOBAL_ATU_OP_GET_NEXT_DB);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_atu_mac_read(ps, next.mac);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_ATU_DATA);
- if (ret < 0)
- return ret;
-
- next.state = ret & GLOBAL_ATU_DATA_STATE_MASK;
- if (next.state != GLOBAL_ATU_DATA_STATE_UNUSED) {
- unsigned int mask, shift;
-
- if (ret & GLOBAL_ATU_DATA_TRUNK) {
- next.trunk = true;
- mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK;
- shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT;
- } else {
- next.trunk = false;
- mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK;
- shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT;
- }
-
- next.portv_trunkid = (ret & mask) >> shift;
- }
-
- *entry = next;
- return 0;
-}
-
-static int _mv88e6xxx_port_fdb_dump_one(struct mv88e6xxx_priv_state *ps,
- u16 fid, u16 vid, int port,
- struct switchdev_obj_port_fdb *fdb,
- int (*cb)(struct switchdev_obj *obj))
-{
- struct mv88e6xxx_atu_entry addr = {
- .mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
- };
- int err;
-
- err = _mv88e6xxx_atu_mac_write(ps, addr.mac);
- if (err)
- return err;
-
- do {
- err = _mv88e6xxx_atu_getnext(ps, fid, &addr);
- if (err)
- break;
-
- if (addr.state == GLOBAL_ATU_DATA_STATE_UNUSED)
- break;
-
- if (!addr.trunk && addr.portv_trunkid & BIT(port)) {
- bool is_static = addr.state ==
- (is_multicast_ether_addr(addr.mac) ?
- GLOBAL_ATU_DATA_STATE_MC_STATIC :
- GLOBAL_ATU_DATA_STATE_UC_STATIC);
-
- fdb->vid = vid;
- ether_addr_copy(fdb->addr, addr.mac);
- fdb->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
-
- err = cb(&fdb->obj);
- if (err)
- break;
- }
- } while (!is_broadcast_ether_addr(addr.mac));
-
- return err;
-}
-
-static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
- struct switchdev_obj_port_fdb *fdb,
- int (*cb)(struct switchdev_obj *obj))
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct mv88e6xxx_vtu_stu_entry vlan = {
- .vid = GLOBAL_VTU_VID_MASK, /* all ones */
- };
- u16 fid;
- int err;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
- return -EOPNOTSUPP;
-
- mutex_lock(&ps->smi_mutex);
-
- /* Dump port's default Filtering Information Database (VLAN ID 0) */
- err = _mv88e6xxx_port_fid_get(ps, port, &fid);
- if (err)
- goto unlock;
-
- err = _mv88e6xxx_port_fdb_dump_one(ps, fid, 0, port, fdb, cb);
- if (err)
- goto unlock;
-
- /* Dump VLANs' Filtering Information Databases */
- err = _mv88e6xxx_vtu_vid_write(ps, vlan.vid);
- if (err)
- goto unlock;
-
- do {
- err = _mv88e6xxx_vtu_getnext(ps, &vlan);
- if (err)
- break;
-
- if (!vlan.valid)
- break;
-
- err = _mv88e6xxx_port_fdb_dump_one(ps, vlan.fid, vlan.vid, port,
- fdb, cb);
- if (err)
- break;
- } while (vlan.vid < GLOBAL_VTU_VID_MASK);
-
-unlock:
- mutex_unlock(&ps->smi_mutex);
-
- return err;
-}
-
-static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
- struct net_device *bridge)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int i, err = 0;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
- return -EOPNOTSUPP;
-
- mutex_lock(&ps->smi_mutex);
-
- /* Assign the bridge and remap each port's VLANTable */
- ps->ports[port].bridge_dev = bridge;
-
- for (i = 0; i < ps->info->num_ports; ++i) {
- if (ps->ports[i].bridge_dev == bridge) {
- err = _mv88e6xxx_port_based_vlan_map(ps, i);
- if (err)
- break;
- }
- }
-
- mutex_unlock(&ps->smi_mutex);
-
- return err;
-}
-
-static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- struct net_device *bridge = ps->ports[port].bridge_dev;
- int i;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
- return;
-
- mutex_lock(&ps->smi_mutex);
-
- /* Unassign the bridge and remap each port's VLANTable */
- ps->ports[port].bridge_dev = NULL;
-
- for (i = 0; i < ps->info->num_ports; ++i)
- if (i == port || ps->ports[i].bridge_dev == bridge)
- if (_mv88e6xxx_port_based_vlan_map(ps, i))
- netdev_warn(ds->ports[i], "failed to remap\n");
-
- mutex_unlock(&ps->smi_mutex);
-}
-
-static int _mv88e6xxx_phy_page_write(struct mv88e6xxx_priv_state *ps,
- int port, int page, int reg, int val)
-{
- int ret;
-
- ret = _mv88e6xxx_phy_write_indirect(ps, port, 0x16, page);
- if (ret < 0)
- goto restore_page_0;
-
- ret = _mv88e6xxx_phy_write_indirect(ps, port, reg, val);
-restore_page_0:
- _mv88e6xxx_phy_write_indirect(ps, port, 0x16, 0x0);
-
- return ret;
-}
-
-static int _mv88e6xxx_phy_page_read(struct mv88e6xxx_priv_state *ps,
- int port, int page, int reg)
-{
- int ret;
-
- ret = _mv88e6xxx_phy_write_indirect(ps, port, 0x16, page);
- if (ret < 0)
- goto restore_page_0;
-
- ret = _mv88e6xxx_phy_read_indirect(ps, port, reg);
-restore_page_0:
- _mv88e6xxx_phy_write_indirect(ps, port, 0x16, 0x0);
-
- return ret;
-}
-
-static int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps)
-{
- bool ppu_active = mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU_ACTIVE);
- u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
- struct gpio_desc *gpiod = ps->reset;
- unsigned long timeout;
- int ret;
- int i;
-
- /* Set all ports to the disabled state. */
- for (i = 0; i < ps->info->num_ports; i++) {
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(i), PORT_CONTROL);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL,
- ret & 0xfffc);
- if (ret)
- return ret;
- }
-
- /* Wait for transmit queues to drain. */
- usleep_range(2000, 4000);
-
- /* If there is a gpio connected to the reset pin, toggle it */
- if (gpiod) {
- gpiod_set_value_cansleep(gpiod, 1);
- usleep_range(10000, 20000);
- gpiod_set_value_cansleep(gpiod, 0);
- usleep_range(10000, 20000);
- }
-
- /* Reset the switch. Keep the PPU active if requested. The PPU
- * needs to be active to support indirect phy register access
- * through global registers 0x18 and 0x19.
- */
- if (ppu_active)
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc000);
- else
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc400);
- if (ret)
- return ret;
-
- /* Wait up to one second for reset to complete. */
- timeout = jiffies + 1 * HZ;
- while (time_before(jiffies, timeout)) {
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00);
- if (ret < 0)
- return ret;
-
- if ((ret & is_reset) == is_reset)
- break;
- usleep_range(1000, 2000);
- }
- if (time_after(jiffies, timeout))
- ret = -ETIMEDOUT;
- else
- ret = 0;
-
- return ret;
-}
-
-static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps)
-{
- int ret;
-
- ret = _mv88e6xxx_phy_page_read(ps, REG_FIBER_SERDES, PAGE_FIBER_SERDES,
- MII_BMCR);
- if (ret < 0)
- return ret;
-
- if (ret & BMCR_PDOWN) {
- ret &= ~BMCR_PDOWN;
- ret = _mv88e6xxx_phy_page_write(ps, REG_FIBER_SERDES,
- PAGE_FIBER_SERDES, MII_BMCR,
- ret);
- }
-
- return ret;
-}
-
-static int mv88e6xxx_setup_port(struct mv88e6xxx_priv_state *ps, int port)
-{
- struct dsa_switch *ds = ps->ds;
- int ret;
- u16 reg;
-
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) ||
- mv88e6xxx_6065_family(ps) || mv88e6xxx_6320_family(ps)) {
- /* MAC Forcing register: don't force link, speed,
- * duplex or flow control state to any particular
- * values on physical ports, but force the CPU port
- * and all DSA ports to their maximum bandwidth and
- * full duplex.
- */
- reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_PCS_CTRL);
- if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
- reg &= ~PORT_PCS_CTRL_UNFORCED;
- reg |= PORT_PCS_CTRL_FORCE_LINK |
- PORT_PCS_CTRL_LINK_UP |
- PORT_PCS_CTRL_DUPLEX_FULL |
- PORT_PCS_CTRL_FORCE_DUPLEX;
- if (mv88e6xxx_6065_family(ps))
- reg |= PORT_PCS_CTRL_100;
- else
- reg |= PORT_PCS_CTRL_1000;
- } else {
- reg |= PORT_PCS_CTRL_UNFORCED;
- }
-
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_PCS_CTRL, reg);
- if (ret)
- return ret;
- }
-
- /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
- * disable Header mode, enable IGMP/MLD snooping, disable VLAN
- * tunneling, determine priority by looking at 802.1p and IP
- * priority fields (IP prio has precedence), and set STP state
- * to Forwarding.
- *
- * If this is the CPU link, use DSA or EDSA tagging depending
- * on which tagging mode was configured.
- *
- * If this is a link to another switch, use DSA tagging mode.
- *
- * If this is the upstream port for this switch, enable
- * forwarding of unknown unicasts and multicasts.
- */
- reg = 0;
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6095_family(ps) || mv88e6xxx_6065_family(ps) ||
- mv88e6xxx_6185_family(ps) || mv88e6xxx_6320_family(ps))
- reg = PORT_CONTROL_IGMP_MLD_SNOOP |
- PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP |
- PORT_CONTROL_STATE_FORWARDING;
- if (dsa_is_cpu_port(ds, port)) {
- if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps))
- reg |= PORT_CONTROL_DSA_TAG;
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6320_family(ps)) {
- if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
- reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA;
- else
- reg |= PORT_CONTROL_FRAME_MODE_DSA;
- reg |= PORT_CONTROL_FORWARD_UNKNOWN |
- PORT_CONTROL_FORWARD_UNKNOWN_MC;
- }
-
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6095_family(ps) || mv88e6xxx_6065_family(ps) ||
- mv88e6xxx_6185_family(ps) || mv88e6xxx_6320_family(ps)) {
- if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
- reg |= PORT_CONTROL_EGRESS_ADD_TAG;
- }
- }
- if (dsa_is_dsa_port(ds, port)) {
- if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps))
- reg |= PORT_CONTROL_DSA_TAG;
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6320_family(ps)) {
- reg |= PORT_CONTROL_FRAME_MODE_DSA;
- }
-
- if (port == dsa_upstream_port(ds))
- reg |= PORT_CONTROL_FORWARD_UNKNOWN |
- PORT_CONTROL_FORWARD_UNKNOWN_MC;
- }
- if (reg) {
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_CONTROL, reg);
- if (ret)
- return ret;
- }
-
- /* If this port is connected to a SerDes, make sure the SerDes is not
- * powered down.
- */
- if (mv88e6xxx_6352_family(ps)) {
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_STATUS);
- if (ret < 0)
- return ret;
- ret &= PORT_STATUS_CMODE_MASK;
- if ((ret == PORT_STATUS_CMODE_100BASE_X) ||
- (ret == PORT_STATUS_CMODE_1000BASE_X) ||
- (ret == PORT_STATUS_CMODE_SGMII)) {
- ret = mv88e6xxx_power_on_serdes(ps);
- if (ret < 0)
- return ret;
- }
- }
-
- /* Port Control 2: don't force a good FCS, set the maximum frame size to
- * 10240 bytes, disable 802.1q tags checking, don't discard tagged or
- * untagged frames on this port, do a destination address lookup on all
- * received packets as usual, disable ARP mirroring and don't send a
- * copy of all transmitted/received frames on this port to the CPU.
- */
- reg = 0;
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6095_family(ps) || mv88e6xxx_6320_family(ps) ||
- mv88e6xxx_6185_family(ps))
- reg = PORT_CONTROL_2_MAP_DA;
-
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6320_family(ps))
- reg |= PORT_CONTROL_2_JUMBO_10240;
-
- if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps)) {
- /* Set the upstream port this port should use */
- reg |= dsa_upstream_port(ds);
- /* enable forwarding of unknown multicast addresses to
- * the upstream port
- */
- if (port == dsa_upstream_port(ds))
- reg |= PORT_CONTROL_2_FORWARD_UNKNOWN;
- }
-
- reg |= PORT_CONTROL_2_8021Q_DISABLED;
-
- if (reg) {
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_CONTROL_2, reg);
- if (ret)
- return ret;
- }
-
- /* Port Association Vector: when learning source addresses
- * of packets, add the address to the address database using
- * a port bitmap that has only the bit for this port set and
- * the other bits clear.
- */
- reg = 1 << port;
- /* Disable learning for CPU port */
- if (dsa_is_cpu_port(ds, port))
- reg = 0;
-
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_ASSOC_VECTOR, reg);
- if (ret)
- return ret;
-
- /* Egress rate control 2: disable egress rate control. */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_RATE_CONTROL_2,
- 0x0000);
- if (ret)
- return ret;
-
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6320_family(ps)) {
- /* Do not limit the period of time that this port can
- * be paused for by the remote end or the period of
- * time that this port can pause the remote end.
- */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_PAUSE_CTRL, 0x0000);
- if (ret)
- return ret;
-
- /* Port ATU control: disable limiting the number of
- * address database entries that this port is allowed
- * to use.
- */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_ATU_CONTROL, 0x0000);
- /* Priority Override: disable DA, SA and VTU priority
- * override.
- */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_PRI_OVERRIDE, 0x0000);
- if (ret)
- return ret;
-
- /* Port Ethertype: use the Ethertype DSA Ethertype
- * value.
- */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_ETH_TYPE, ETH_P_EDSA);
- if (ret)
- return ret;
- /* Tag Remap: use an identity 802.1p prio -> switch
- * prio mapping.
- */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_TAG_REGMAP_0123, 0x3210);
- if (ret)
- return ret;
-
- /* Tag Remap 2: use an identity 802.1p prio -> switch
- * prio mapping.
- */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_TAG_REGMAP_4567, 0x7654);
- if (ret)
- return ret;
- }
-
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) ||
- mv88e6xxx_6320_family(ps)) {
- /* Rate Control: disable ingress rate limiting. */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
- PORT_RATE_CONTROL, 0x0001);
- if (ret)
- return ret;
- }
-
- /* Port Control 1: disable trunking, disable sending
- * learning messages to this port.
- */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1, 0x0000);
- if (ret)
- return ret;
-
- /* Port based VLAN map: give each port the same default address
- * database, and allow bidirectional communication between the
- * CPU and DSA port(s), and the other ports.
- */
- ret = _mv88e6xxx_port_fid_set(ps, port, 0);
- if (ret)
- return ret;
-
- ret = _mv88e6xxx_port_based_vlan_map(ps, port);
- if (ret)
- return ret;
-
- /* Default VLAN ID and priority: don't set a default VLAN
- * ID, and set the default packet priority to zero.
- */
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_DEFAULT_VLAN,
- 0x0000);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static int mv88e6xxx_setup_global(struct mv88e6xxx_priv_state *ps)
-{
- struct dsa_switch *ds = ps->ds;
- u32 upstream_port = dsa_upstream_port(ds);
- u16 reg;
- int err;
- int i;
-
- /* Enable the PHY Polling Unit if present, don't discard any packets,
- * and mask all interrupt sources.
- */
- reg = 0;
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU) ||
- mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU_ACTIVE))
- reg |= GLOBAL_CONTROL_PPU_ENABLE;
-
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, reg);
- if (err)
- return err;
-
- /* Configure the upstream port, and configure it as the port to which
- * ingress and egress and ARP monitor frames are to be sent.
- */
- reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
- if (err)
- return err;
-
- /* Disable remote management, and set the switch's DSA device number. */
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
- GLOBAL_CONTROL_2_MULTIPLE_CASCADE |
- (ds->index & 0x1f));
- if (err)
- return err;
-
- /* Set the default address aging time to 5 minutes, and
- * enable address learn messages to be sent to all message
- * ports.
- */
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL,
- 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL);
- if (err)
- return err;
-
- /* Configure the IP ToS mapping registers. */
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
- if (err)
- return err;
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
- if (err)
- return err;
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
- if (err)
- return err;
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
- if (err)
- return err;
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
- if (err)
- return err;
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
- if (err)
- return err;
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
- if (err)
- return err;
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
- if (err)
- return err;
-
- /* Configure the IEEE 802.1p priority mapping register. */
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
- if (err)
- return err;
-
- /* Send all frames with destination addresses matching
- * 01:80:c2:00:00:0x to the CPU port.
- */
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);
- if (err)
- return err;
-
- /* Ignore removed tag data on doubly tagged packets, disable
- * flow control messages, force flow control priority to the
- * highest, and send all special multicast frames to the CPU
- * port at the highest priority.
- */
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SWITCH_MGMT,
- 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 |
- GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI);
- if (err)
- return err;
-
- /* Program the DSA routing table. */
- for (i = 0; i < 32; i++) {
- int nexthop = 0x1f;
-
- if (ps->ds->cd->rtable &&
- i != ps->ds->index && i < ps->ds->dst->pd->nr_chips)
- nexthop = ps->ds->cd->rtable[i] & 0x1f;
-
- err = _mv88e6xxx_reg_write(
- ps, REG_GLOBAL2,
- GLOBAL2_DEVICE_MAPPING,
- GLOBAL2_DEVICE_MAPPING_UPDATE |
- (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop);
- if (err)
- return err;
- }
-
- /* Clear all trunk masks. */
- for (i = 0; i < 8; i++) {
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
- 0x8000 |
- (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
- ((1 << ps->info->num_ports) - 1));
- if (err)
- return err;
- }
-
- /* Clear all trunk mappings. */
- for (i = 0; i < 16; i++) {
- err = _mv88e6xxx_reg_write(
- ps, REG_GLOBAL2,
- GLOBAL2_TRUNK_MAPPING,
- GLOBAL2_TRUNK_MAPPING_UPDATE |
- (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT));
- if (err)
- return err;
- }
-
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6320_family(ps)) {
- /* Send all frames with destination addresses matching
- * 01:80:c2:00:00:2x to the CPU port.
- */
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
- GLOBAL2_MGMT_EN_2X, 0xffff);
- if (err)
- return err;
-
- /* Initialise cross-chip port VLAN table to reset
- * defaults.
- */
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
- GLOBAL2_PVT_ADDR, 0x9000);
- if (err)
- return err;
-
- /* Clear the priority override table. */
- for (i = 0; i < 16; i++) {
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
- GLOBAL2_PRIO_OVERRIDE,
- 0x8000 | (i << 8));
- if (err)
- return err;
- }
- }
-
- if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
- mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
- mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) ||
- mv88e6xxx_6320_family(ps)) {
- /* Disable ingress rate limiting by resetting all
- * ingress rate limit registers to their initial
- * state.
- */
- for (i = 0; i < ps->info->num_ports; i++) {
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
- GLOBAL2_INGRESS_OP,
- 0x9000 | (i << 8));
- if (err)
- return err;
- }
- }
-
- /* Clear the statistics counters for all ports */
- err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,
- GLOBAL_STATS_OP_FLUSH_ALL);
- if (err)
- return err;
-
- /* Wait for the flush to complete. */
- err = _mv88e6xxx_stats_wait(ps);
- if (err)
- return err;
-
- /* Clear all ATU entries */
- err = _mv88e6xxx_atu_flush(ps, 0, true);
- if (err)
- return err;
-
- /* Clear all the VTU and STU entries */
- err = _mv88e6xxx_vtu_stu_flush(ps);
- if (err < 0)
- return err;
-
- return err;
-}
-
-static int mv88e6xxx_setup(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int err;
- int i;
-
- ps->ds = ds;
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
- mutex_init(&ps->eeprom_mutex);
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
- mv88e6xxx_ppu_state_init(ps);
-
- mutex_lock(&ps->smi_mutex);
-
- err = mv88e6xxx_switch_reset(ps);
- if (err)
- goto unlock;
-
- err = mv88e6xxx_setup_global(ps);
- if (err)
- goto unlock;
-
- for (i = 0; i < ps->info->num_ports; i++) {
- err = mv88e6xxx_setup_port(ps, i);
- if (err)
- goto unlock;
- }
-
-unlock:
- mutex_unlock(&ps->smi_mutex);
-
- return err;
-}
-
-int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_page_read(ps, port, page, reg);
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
-int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
- int reg, int val)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_page_write(ps, port, page, reg, val);
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
-static int mv88e6xxx_port_to_phy_addr(struct mv88e6xxx_priv_state *ps,
- int port)
-{
- if (port >= 0 && port < ps->info->num_ports)
- return port;
- return -EINVAL;
-}
-
-static int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int addr = mv88e6xxx_port_to_phy_addr(ps, port);
- int ret;
-
- if (addr < 0)
- return 0xffff;
-
- mutex_lock(&ps->smi_mutex);
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
- ret = mv88e6xxx_phy_read_ppu(ps, addr, regnum);
- else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
- ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum);
- else
- ret = _mv88e6xxx_phy_read(ps, addr, regnum);
-
- mutex_unlock(&ps->smi_mutex);
- return ret;
-}
-
-static int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum,
- u16 val)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int addr = mv88e6xxx_port_to_phy_addr(ps, port);
- int ret;
-
- if (addr < 0)
- return 0xffff;
-
- mutex_lock(&ps->smi_mutex);
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
- ret = mv88e6xxx_phy_write_ppu(ps, addr, regnum, val);
- else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
- ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
- else
- ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
-
- mutex_unlock(&ps->smi_mutex);
- return ret;
-}
-
-#ifdef CONFIG_NET_DSA_HWMON
-
-static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
- int val;
-
- *temp = 0;
-
- mutex_lock(&ps->smi_mutex);
-
- ret = _mv88e6xxx_phy_write(ps, 0x0, 0x16, 0x6);
- if (ret < 0)
- goto error;
-
- /* Enable temperature sensor */
- ret = _mv88e6xxx_phy_read(ps, 0x0, 0x1a);
- if (ret < 0)
- goto error;
-
- ret = _mv88e6xxx_phy_write(ps, 0x0, 0x1a, ret | (1 << 5));
- if (ret < 0)
- goto error;
-
- /* Wait for temperature to stabilize */
- usleep_range(10000, 12000);
-
- val = _mv88e6xxx_phy_read(ps, 0x0, 0x1a);
- if (val < 0) {
- ret = val;
- goto error;
- }
-
- /* Disable temperature sensor */
- ret = _mv88e6xxx_phy_write(ps, 0x0, 0x1a, ret & ~(1 << 5));
- if (ret < 0)
- goto error;
-
- *temp = ((val & 0x1f) - 5) * 5;
-
-error:
- _mv88e6xxx_phy_write(ps, 0x0, 0x16, 0x0);
- mutex_unlock(&ps->smi_mutex);
- return ret;
-}
-
-static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
- int ret;
-
- *temp = 0;
-
- ret = mv88e6xxx_phy_page_read(ds, phy, 6, 27);
- if (ret < 0)
- return ret;
-
- *temp = (ret & 0xff) - 25;
-
- return 0;
-}
-
-static int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP))
- return -EOPNOTSUPP;
-
- if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps))
- return mv88e63xx_get_temp(ds, temp);
-
- return mv88e61xx_get_temp(ds, temp);
-}
-
-static int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
- int ret;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
- return -EOPNOTSUPP;
-
- *temp = 0;
-
- ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26);
- if (ret < 0)
- return ret;
-
- *temp = (((ret >> 8) & 0x1f) * 5) - 25;
-
- return 0;
-}
-
-static int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
- int ret;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
- return -EOPNOTSUPP;
-
- ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26);
- if (ret < 0)
- return ret;
- temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f);
- return mv88e6xxx_phy_page_write(ds, phy, 6, 26,
- (ret & 0xe0ff) | (temp << 8));
-}
-
-static int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
- int ret;
-
- if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
- return -EOPNOTSUPP;
-
- *alarm = false;
-
- ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26);
- if (ret < 0)
- return ret;
-
- *alarm = !!(ret & 0x40);
-
- return 0;
-}
-#endif /* CONFIG_NET_DSA_HWMON */
-
-static const struct mv88e6xxx_info mv88e6xxx_table[] = {
- [MV88E6085] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6085,
- .family = MV88E6XXX_FAMILY_6097,
- .name = "Marvell 88E6085",
- .num_databases = 4096,
- .num_ports = 10,
- .flags = MV88E6XXX_FLAGS_FAMILY_6097,
- },
-
- [MV88E6095] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6095,
- .family = MV88E6XXX_FAMILY_6095,
- .name = "Marvell 88E6095/88E6095F",
- .num_databases = 256,
- .num_ports = 11,
- .flags = MV88E6XXX_FLAGS_FAMILY_6095,
- },
-
- [MV88E6123] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6123,
- .family = MV88E6XXX_FAMILY_6165,
- .name = "Marvell 88E6123",
- .num_databases = 4096,
- .num_ports = 3,
- .flags = MV88E6XXX_FLAGS_FAMILY_6165,
- },
-
- [MV88E6131] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6131,
- .family = MV88E6XXX_FAMILY_6185,
- .name = "Marvell 88E6131",
- .num_databases = 256,
- .num_ports = 8,
- .flags = MV88E6XXX_FLAGS_FAMILY_6185,
- },
-
- [MV88E6161] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6161,
- .family = MV88E6XXX_FAMILY_6165,
- .name = "Marvell 88E6161",
- .num_databases = 4096,
- .num_ports = 6,
- .flags = MV88E6XXX_FLAGS_FAMILY_6165,
- },
-
- [MV88E6165] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6165,
- .family = MV88E6XXX_FAMILY_6165,
- .name = "Marvell 88E6165",
- .num_databases = 4096,
- .num_ports = 6,
- .flags = MV88E6XXX_FLAGS_FAMILY_6165,
- },
-
- [MV88E6171] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6171,
- .family = MV88E6XXX_FAMILY_6351,
- .name = "Marvell 88E6171",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6351,
- },
-
- [MV88E6172] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6172,
- .family = MV88E6XXX_FAMILY_6352,
- .name = "Marvell 88E6172",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6352,
- },
-
- [MV88E6175] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6175,
- .family = MV88E6XXX_FAMILY_6351,
- .name = "Marvell 88E6175",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6351,
- },
-
- [MV88E6176] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6176,
- .family = MV88E6XXX_FAMILY_6352,
- .name = "Marvell 88E6176",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6352,
- },
-
- [MV88E6185] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6185,
- .family = MV88E6XXX_FAMILY_6185,
- .name = "Marvell 88E6185",
- .num_databases = 256,
- .num_ports = 10,
- .flags = MV88E6XXX_FLAGS_FAMILY_6185,
- },
-
- [MV88E6240] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
- .family = MV88E6XXX_FAMILY_6352,
- .name = "Marvell 88E6240",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6352,
- },
-
- [MV88E6320] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6320,
- .family = MV88E6XXX_FAMILY_6320,
- .name = "Marvell 88E6320",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6320,
- },
-
- [MV88E6321] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6321,
- .family = MV88E6XXX_FAMILY_6320,
- .name = "Marvell 88E6321",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6320,
- },
-
- [MV88E6350] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6350,
- .family = MV88E6XXX_FAMILY_6351,
- .name = "Marvell 88E6350",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6351,
- },
-
- [MV88E6351] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6351,
- .family = MV88E6XXX_FAMILY_6351,
- .name = "Marvell 88E6351",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6351,
- },
-
- [MV88E6352] = {
- .prod_num = PORT_SWITCH_ID_PROD_NUM_6352,
- .family = MV88E6XXX_FAMILY_6352,
- .name = "Marvell 88E6352",
- .num_databases = 4096,
- .num_ports = 7,
- .flags = MV88E6XXX_FLAGS_FAMILY_6352,
- },
-};
-
-static const struct mv88e6xxx_info *
-mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table,
- unsigned int num)
-{
- int i;
-
- for (i = 0; i < num; ++i)
- if (table[i].prod_num == prod_num)
- return &table[i];
-
- return NULL;
-}
-
-static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
- struct device *host_dev, int sw_addr,
- void **priv)
-{
- const struct mv88e6xxx_info *info;
- struct mv88e6xxx_priv_state *ps;
- struct mii_bus *bus;
- const char *name;
- int id, prod_num, rev;
-
- bus = dsa_host_dev_to_mii_bus(host_dev);
- if (!bus)
- return NULL;
-
- id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
- if (id < 0)
- return NULL;
-
- prod_num = (id & 0xfff0) >> 4;
- rev = id & 0x000f;
-
- info = mv88e6xxx_lookup_info(prod_num, mv88e6xxx_table,
- ARRAY_SIZE(mv88e6xxx_table));
- if (!info)
- return NULL;
-
- name = info->name;
-
- ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
- if (!ps)
- return NULL;
-
- ps->bus = bus;
- ps->sw_addr = sw_addr;
- ps->info = info;
- mutex_init(&ps->smi_mutex);
-
- *priv = ps;
-
- dev_info(&ps->bus->dev, "switch 0x%x probed: %s, revision %u\n",
- prod_num, name, rev);
-
- return name;
-}
-
-struct dsa_switch_driver mv88e6xxx_switch_driver = {
- .tag_protocol = DSA_TAG_PROTO_EDSA,
- .probe = mv88e6xxx_drv_probe,
- .setup = mv88e6xxx_setup,
- .set_addr = mv88e6xxx_set_addr,
- .phy_read = mv88e6xxx_phy_read,
- .phy_write = mv88e6xxx_phy_write,
- .adjust_link = mv88e6xxx_adjust_link,
- .get_strings = mv88e6xxx_get_strings,
- .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
- .get_sset_count = mv88e6xxx_get_sset_count,
- .set_eee = mv88e6xxx_set_eee,
- .get_eee = mv88e6xxx_get_eee,
-#ifdef CONFIG_NET_DSA_HWMON
- .get_temp = mv88e6xxx_get_temp,
- .get_temp_limit = mv88e6xxx_get_temp_limit,
- .set_temp_limit = mv88e6xxx_set_temp_limit,
- .get_temp_alarm = mv88e6xxx_get_temp_alarm,
-#endif
- .get_eeprom_len = mv88e6xxx_get_eeprom_len,
- .get_eeprom = mv88e6xxx_get_eeprom,
- .set_eeprom = mv88e6xxx_set_eeprom,
- .get_regs_len = mv88e6xxx_get_regs_len,
- .get_regs = mv88e6xxx_get_regs,
- .port_bridge_join = mv88e6xxx_port_bridge_join,
- .port_bridge_leave = mv88e6xxx_port_bridge_leave,
- .port_stp_state_set = mv88e6xxx_port_stp_state_set,
- .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
- .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
- .port_vlan_add = mv88e6xxx_port_vlan_add,
- .port_vlan_del = mv88e6xxx_port_vlan_del,
- .port_vlan_dump = mv88e6xxx_port_vlan_dump,
- .port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
- .port_fdb_add = mv88e6xxx_port_fdb_add,
- .port_fdb_del = mv88e6xxx_port_fdb_del,
- .port_fdb_dump = mv88e6xxx_port_fdb_dump,
-};
-
-int mv88e6xxx_probe(struct mdio_device *mdiodev)
-{
- struct device *dev = &mdiodev->dev;
- struct device_node *np = dev->of_node;
- struct mv88e6xxx_priv_state *ps;
- int id, prod_num, rev;
- struct dsa_switch *ds;
- u32 eeprom_len;
- int err;
-
- ds = devm_kzalloc(dev, sizeof(*ds) + sizeof(*ps), GFP_KERNEL);
- if (!ds)
- return -ENOMEM;
-
- ps = (struct mv88e6xxx_priv_state *)(ds + 1);
- ds->priv = ps;
- ds->dev = dev;
- ps->dev = dev;
- ps->ds = ds;
- ps->bus = mdiodev->bus;
- ps->sw_addr = mdiodev->addr;
- mutex_init(&ps->smi_mutex);
-
- get_device(&ps->bus->dev);
-
- ds->drv = &mv88e6xxx_switch_driver;
-
- id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
- if (id < 0)
- return id;
-
- prod_num = (id & 0xfff0) >> 4;
- rev = id & 0x000f;
-
- ps->info = mv88e6xxx_lookup_info(prod_num, mv88e6xxx_table,
- ARRAY_SIZE(mv88e6xxx_table));
- if (!ps->info)
- return -ENODEV;
-
- ps->reset = devm_gpiod_get(&mdiodev->dev, "reset", GPIOD_ASIS);
- if (IS_ERR(ps->reset)) {
- err = PTR_ERR(ps->reset);
- if (err == -ENOENT) {
- /* Optional, so not an error */
- ps->reset = NULL;
- } else {
- return err;
- }
- }
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM) &&
- !of_property_read_u32(np, "eeprom-length", &eeprom_len))
- ps->eeprom_len = eeprom_len;
-
- dev_set_drvdata(dev, ds);
-
- dev_info(dev, "switch 0x%x probed: %s, revision %u\n",
- prod_num, ps->info->name, rev);
-
- return 0;
-}
-
-static void mv88e6xxx_remove(struct mdio_device *mdiodev)
-{
- struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- put_device(&ps->bus->dev);
-}
-
-static const struct of_device_id mv88e6xxx_of_match[] = {
- { .compatible = "marvell,mv88e6085" },
- { /* sentinel */ },
-};
-
-MODULE_DEVICE_TABLE(of, mv88e6xxx_of_match);
-
-static struct mdio_driver mv88e6xxx_driver = {
- .probe = mv88e6xxx_probe,
- .remove = mv88e6xxx_remove,
- .mdiodrv.driver = {
- .name = "mv88e6085",
- .of_match_table = mv88e6xxx_of_match,
- },
-};
-
-static int __init mv88e6xxx_init(void)
-{
- register_switch_driver(&mv88e6xxx_switch_driver);
- return mdio_driver_register(&mv88e6xxx_driver);
-}
-module_init(mv88e6xxx_init);
-
-static void __exit mv88e6xxx_cleanup(void)
-{
- mdio_driver_unregister(&mv88e6xxx_driver);
- unregister_switch_driver(&mv88e6xxx_switch_driver);
-}
-module_exit(mv88e6xxx_cleanup);
-
-MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
-MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
deleted file mode 100644
index 36d0e1504..000000000
--- a/drivers/net/dsa/mv88e6xxx.h
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * net/dsa/mv88e6xxx.h - Marvell 88e6xxx switch chip support
- * Copyright (c) 2008 Marvell Semiconductor
- *
- * 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.
- */
-
-#ifndef __MV88E6XXX_H
-#define __MV88E6XXX_H
-
-#include <linux/if_vlan.h>
-#include <linux/gpio/consumer.h>
-
-#ifndef UINT64_MAX
-#define UINT64_MAX (u64)(~((u64)0))
-#endif
-
-#define SMI_CMD 0x00
-#define SMI_CMD_BUSY BIT(15)
-#define SMI_CMD_CLAUSE_22 BIT(12)
-#define SMI_CMD_OP_22_WRITE ((1 << 10) | SMI_CMD_BUSY | SMI_CMD_CLAUSE_22)
-#define SMI_CMD_OP_22_READ ((2 << 10) | SMI_CMD_BUSY | SMI_CMD_CLAUSE_22)
-#define SMI_CMD_OP_45_WRITE_ADDR ((0 << 10) | SMI_CMD_BUSY)
-#define SMI_CMD_OP_45_WRITE_DATA ((1 << 10) | SMI_CMD_BUSY)
-#define SMI_CMD_OP_45_READ_DATA ((2 << 10) | SMI_CMD_BUSY)
-#define SMI_CMD_OP_45_READ_DATA_INC ((3 << 10) | SMI_CMD_BUSY)
-#define SMI_DATA 0x01
-
-/* Fiber/SERDES Registers are located at SMI address F, page 1 */
-#define REG_FIBER_SERDES 0x0f
-#define PAGE_FIBER_SERDES 0x01
-
-#define REG_PORT(p) (0x10 + (p))
-#define PORT_STATUS 0x00
-#define PORT_STATUS_PAUSE_EN BIT(15)
-#define PORT_STATUS_MY_PAUSE BIT(14)
-#define PORT_STATUS_HD_FLOW BIT(13)
-#define PORT_STATUS_PHY_DETECT BIT(12)
-#define PORT_STATUS_LINK BIT(11)
-#define PORT_STATUS_DUPLEX BIT(10)
-#define PORT_STATUS_SPEED_MASK 0x0300
-#define PORT_STATUS_SPEED_10 0x0000
-#define PORT_STATUS_SPEED_100 0x0100
-#define PORT_STATUS_SPEED_1000 0x0200
-#define PORT_STATUS_EEE BIT(6) /* 6352 */
-#define PORT_STATUS_AM_DIS BIT(6) /* 6165 */
-#define PORT_STATUS_MGMII BIT(6) /* 6185 */
-#define PORT_STATUS_TX_PAUSED BIT(5)
-#define PORT_STATUS_FLOW_CTRL BIT(4)
-#define PORT_STATUS_CMODE_MASK 0x0f
-#define PORT_STATUS_CMODE_100BASE_X 0x8
-#define PORT_STATUS_CMODE_1000BASE_X 0x9
-#define PORT_STATUS_CMODE_SGMII 0xa
-#define PORT_PCS_CTRL 0x01
-#define PORT_PCS_CTRL_RGMII_DELAY_RXCLK BIT(15)
-#define PORT_PCS_CTRL_RGMII_DELAY_TXCLK BIT(14)
-#define PORT_PCS_CTRL_FC BIT(7)
-#define PORT_PCS_CTRL_FORCE_FC BIT(6)
-#define PORT_PCS_CTRL_LINK_UP BIT(5)
-#define PORT_PCS_CTRL_FORCE_LINK BIT(4)
-#define PORT_PCS_CTRL_DUPLEX_FULL BIT(3)
-#define PORT_PCS_CTRL_FORCE_DUPLEX BIT(2)
-#define PORT_PCS_CTRL_10 0x00
-#define PORT_PCS_CTRL_100 0x01
-#define PORT_PCS_CTRL_1000 0x02
-#define PORT_PCS_CTRL_UNFORCED 0x03
-#define PORT_PAUSE_CTRL 0x02
-#define PORT_SWITCH_ID 0x03
-#define PORT_SWITCH_ID_PROD_NUM_6085 0x04a
-#define PORT_SWITCH_ID_PROD_NUM_6095 0x095
-#define PORT_SWITCH_ID_PROD_NUM_6131 0x106
-#define PORT_SWITCH_ID_PROD_NUM_6320 0x115
-#define PORT_SWITCH_ID_PROD_NUM_6123 0x121
-#define PORT_SWITCH_ID_PROD_NUM_6161 0x161
-#define PORT_SWITCH_ID_PROD_NUM_6165 0x165
-#define PORT_SWITCH_ID_PROD_NUM_6171 0x171
-#define PORT_SWITCH_ID_PROD_NUM_6172 0x172
-#define PORT_SWITCH_ID_PROD_NUM_6175 0x175
-#define PORT_SWITCH_ID_PROD_NUM_6176 0x176
-#define PORT_SWITCH_ID_PROD_NUM_6185 0x1a7
-#define PORT_SWITCH_ID_PROD_NUM_6240 0x240
-#define PORT_SWITCH_ID_PROD_NUM_6321 0x310
-#define PORT_SWITCH_ID_PROD_NUM_6352 0x352
-#define PORT_SWITCH_ID_PROD_NUM_6350 0x371
-#define PORT_SWITCH_ID_PROD_NUM_6351 0x375
-#define PORT_CONTROL 0x04
-#define PORT_CONTROL_USE_CORE_TAG BIT(15)
-#define PORT_CONTROL_DROP_ON_LOCK BIT(14)
-#define PORT_CONTROL_EGRESS_UNMODIFIED (0x0 << 12)
-#define PORT_CONTROL_EGRESS_UNTAGGED (0x1 << 12)
-#define PORT_CONTROL_EGRESS_TAGGED (0x2 << 12)
-#define PORT_CONTROL_EGRESS_ADD_TAG (0x3 << 12)
-#define PORT_CONTROL_HEADER BIT(11)
-#define PORT_CONTROL_IGMP_MLD_SNOOP BIT(10)
-#define PORT_CONTROL_DOUBLE_TAG BIT(9)
-#define PORT_CONTROL_FRAME_MODE_NORMAL (0x0 << 8)
-#define PORT_CONTROL_FRAME_MODE_DSA (0x1 << 8)
-#define PORT_CONTROL_FRAME_MODE_PROVIDER (0x2 << 8)
-#define PORT_CONTROL_FRAME_ETHER_TYPE_DSA (0x3 << 8)
-#define PORT_CONTROL_DSA_TAG BIT(8)
-#define PORT_CONTROL_VLAN_TUNNEL BIT(7)
-#define PORT_CONTROL_TAG_IF_BOTH BIT(6)
-#define PORT_CONTROL_USE_IP BIT(5)
-#define PORT_CONTROL_USE_TAG BIT(4)
-#define PORT_CONTROL_FORWARD_UNKNOWN_MC BIT(3)
-#define PORT_CONTROL_FORWARD_UNKNOWN BIT(2)
-#define PORT_CONTROL_STATE_MASK 0x03
-#define PORT_CONTROL_STATE_DISABLED 0x00
-#define PORT_CONTROL_STATE_BLOCKING 0x01
-#define PORT_CONTROL_STATE_LEARNING 0x02
-#define PORT_CONTROL_STATE_FORWARDING 0x03
-#define PORT_CONTROL_1 0x05
-#define PORT_CONTROL_1_FID_11_4_MASK (0xff << 0)
-#define PORT_BASE_VLAN 0x06
-#define PORT_BASE_VLAN_FID_3_0_MASK (0xf << 12)
-#define PORT_DEFAULT_VLAN 0x07
-#define PORT_DEFAULT_VLAN_MASK 0xfff
-#define PORT_CONTROL_2 0x08
-#define PORT_CONTROL_2_IGNORE_FCS BIT(15)
-#define PORT_CONTROL_2_VTU_PRI_OVERRIDE BIT(14)
-#define PORT_CONTROL_2_SA_PRIO_OVERRIDE BIT(13)
-#define PORT_CONTROL_2_DA_PRIO_OVERRIDE BIT(12)
-#define PORT_CONTROL_2_JUMBO_1522 (0x00 << 12)
-#define PORT_CONTROL_2_JUMBO_2048 (0x01 << 12)
-#define PORT_CONTROL_2_JUMBO_10240 (0x02 << 12)
-#define PORT_CONTROL_2_8021Q_MASK (0x03 << 10)
-#define PORT_CONTROL_2_8021Q_DISABLED (0x00 << 10)
-#define PORT_CONTROL_2_8021Q_FALLBACK (0x01 << 10)
-#define PORT_CONTROL_2_8021Q_CHECK (0x02 << 10)
-#define PORT_CONTROL_2_8021Q_SECURE (0x03 << 10)
-#define PORT_CONTROL_2_DISCARD_TAGGED BIT(9)
-#define PORT_CONTROL_2_DISCARD_UNTAGGED BIT(8)
-#define PORT_CONTROL_2_MAP_DA BIT(7)
-#define PORT_CONTROL_2_DEFAULT_FORWARD BIT(6)
-#define PORT_CONTROL_2_FORWARD_UNKNOWN BIT(6)
-#define PORT_CONTROL_2_EGRESS_MONITOR BIT(5)
-#define PORT_CONTROL_2_INGRESS_MONITOR BIT(4)
-#define PORT_RATE_CONTROL 0x09
-#define PORT_RATE_CONTROL_2 0x0a
-#define PORT_ASSOC_VECTOR 0x0b
-#define PORT_ASSOC_VECTOR_HOLD_AT_1 BIT(15)
-#define PORT_ASSOC_VECTOR_INT_AGE_OUT BIT(14)
-#define PORT_ASSOC_VECTOR_LOCKED_PORT BIT(13)
-#define PORT_ASSOC_VECTOR_IGNORE_WRONG BIT(12)
-#define PORT_ASSOC_VECTOR_REFRESH_LOCKED BIT(11)
-#define PORT_ATU_CONTROL 0x0c
-#define PORT_PRI_OVERRIDE 0x0d
-#define PORT_ETH_TYPE 0x0f
-#define PORT_IN_DISCARD_LO 0x10
-#define PORT_IN_DISCARD_HI 0x11
-#define PORT_IN_FILTERED 0x12
-#define PORT_OUT_FILTERED 0x13
-#define PORT_TAG_REGMAP_0123 0x18
-#define PORT_TAG_REGMAP_4567 0x19
-
-#define REG_GLOBAL 0x1b
-#define GLOBAL_STATUS 0x00
-#define GLOBAL_STATUS_PPU_STATE BIT(15) /* 6351 and 6171 */
-/* Two bits for 6165, 6185 etc */
-#define GLOBAL_STATUS_PPU_MASK (0x3 << 14)
-#define GLOBAL_STATUS_PPU_DISABLED_RST (0x0 << 14)
-#define GLOBAL_STATUS_PPU_INITIALIZING (0x1 << 14)
-#define GLOBAL_STATUS_PPU_DISABLED (0x2 << 14)
-#define GLOBAL_STATUS_PPU_POLLING (0x3 << 14)
-#define GLOBAL_MAC_01 0x01
-#define GLOBAL_MAC_23 0x02
-#define GLOBAL_MAC_45 0x03
-#define GLOBAL_ATU_FID 0x01 /* 6097 6165 6351 6352 */
-#define GLOBAL_VTU_FID 0x02 /* 6097 6165 6351 6352 */
-#define GLOBAL_VTU_FID_MASK 0xfff
-#define GLOBAL_VTU_SID 0x03 /* 6097 6165 6351 6352 */
-#define GLOBAL_VTU_SID_MASK 0x3f
-#define GLOBAL_CONTROL 0x04
-#define GLOBAL_CONTROL_SW_RESET BIT(15)
-#define GLOBAL_CONTROL_PPU_ENABLE BIT(14)
-#define GLOBAL_CONTROL_DISCARD_EXCESS BIT(13) /* 6352 */
-#define GLOBAL_CONTROL_SCHED_PRIO BIT(11) /* 6152 */
-#define GLOBAL_CONTROL_MAX_FRAME_1632 BIT(10) /* 6152 */
-#define GLOBAL_CONTROL_RELOAD_EEPROM BIT(9) /* 6152 */
-#define GLOBAL_CONTROL_DEVICE_EN BIT(7)
-#define GLOBAL_CONTROL_STATS_DONE_EN BIT(6)
-#define GLOBAL_CONTROL_VTU_PROBLEM_EN BIT(5)
-#define GLOBAL_CONTROL_VTU_DONE_EN BIT(4)
-#define GLOBAL_CONTROL_ATU_PROBLEM_EN BIT(3)
-#define GLOBAL_CONTROL_ATU_DONE_EN BIT(2)
-#define GLOBAL_CONTROL_TCAM_EN BIT(1)
-#define GLOBAL_CONTROL_EEPROM_DONE_EN BIT(0)
-#define GLOBAL_VTU_OP 0x05
-#define GLOBAL_VTU_OP_BUSY BIT(15)
-#define GLOBAL_VTU_OP_FLUSH_ALL ((0x01 << 12) | GLOBAL_VTU_OP_BUSY)
-#define GLOBAL_VTU_OP_VTU_LOAD_PURGE ((0x03 << 12) | GLOBAL_VTU_OP_BUSY)
-#define GLOBAL_VTU_OP_VTU_GET_NEXT ((0x04 << 12) | GLOBAL_VTU_OP_BUSY)
-#define GLOBAL_VTU_OP_STU_LOAD_PURGE ((0x05 << 12) | GLOBAL_VTU_OP_BUSY)
-#define GLOBAL_VTU_OP_STU_GET_NEXT ((0x06 << 12) | GLOBAL_VTU_OP_BUSY)
-#define GLOBAL_VTU_VID 0x06
-#define GLOBAL_VTU_VID_MASK 0xfff
-#define GLOBAL_VTU_VID_VALID BIT(12)
-#define GLOBAL_VTU_DATA_0_3 0x07
-#define GLOBAL_VTU_DATA_4_7 0x08
-#define GLOBAL_VTU_DATA_8_11 0x09
-#define GLOBAL_VTU_STU_DATA_MASK 0x03
-#define GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED 0x00
-#define GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED 0x01
-#define GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED 0x02
-#define GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER 0x03
-#define GLOBAL_STU_DATA_PORT_STATE_DISABLED 0x00
-#define GLOBAL_STU_DATA_PORT_STATE_BLOCKING 0x01
-#define GLOBAL_STU_DATA_PORT_STATE_LEARNING 0x02
-#define GLOBAL_STU_DATA_PORT_STATE_FORWARDING 0x03
-#define GLOBAL_ATU_CONTROL 0x0a
-#define GLOBAL_ATU_CONTROL_LEARN2ALL BIT(3)
-#define GLOBAL_ATU_OP 0x0b
-#define GLOBAL_ATU_OP_BUSY BIT(15)
-#define GLOBAL_ATU_OP_NOP (0 << 12)
-#define GLOBAL_ATU_OP_FLUSH_MOVE_ALL ((1 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC ((2 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_OP_LOAD_DB ((3 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_OP_GET_NEXT_DB ((4 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB ((5 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY)
-#define GLOBAL_ATU_DATA 0x0c
-#define GLOBAL_ATU_DATA_TRUNK BIT(15)
-#define GLOBAL_ATU_DATA_TRUNK_ID_MASK 0x00f0
-#define GLOBAL_ATU_DATA_TRUNK_ID_SHIFT 4
-#define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0
-#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4
-#define GLOBAL_ATU_DATA_STATE_MASK 0x0f
-#define GLOBAL_ATU_DATA_STATE_UNUSED 0x00
-#define GLOBAL_ATU_DATA_STATE_UC_MGMT 0x0d
-#define GLOBAL_ATU_DATA_STATE_UC_STATIC 0x0e
-#define GLOBAL_ATU_DATA_STATE_UC_PRIO_OVER 0x0f
-#define GLOBAL_ATU_DATA_STATE_MC_NONE_RATE 0x05
-#define GLOBAL_ATU_DATA_STATE_MC_STATIC 0x07
-#define GLOBAL_ATU_DATA_STATE_MC_MGMT 0x0e
-#define GLOBAL_ATU_DATA_STATE_MC_PRIO_OVER 0x0f
-#define GLOBAL_ATU_MAC_01 0x0d
-#define GLOBAL_ATU_MAC_23 0x0e
-#define GLOBAL_ATU_MAC_45 0x0f
-#define GLOBAL_IP_PRI_0 0x10
-#define GLOBAL_IP_PRI_1 0x11
-#define GLOBAL_IP_PRI_2 0x12
-#define GLOBAL_IP_PRI_3 0x13
-#define GLOBAL_IP_PRI_4 0x14
-#define GLOBAL_IP_PRI_5 0x15
-#define GLOBAL_IP_PRI_6 0x16
-#define GLOBAL_IP_PRI_7 0x17
-#define GLOBAL_IEEE_PRI 0x18
-#define GLOBAL_CORE_TAG_TYPE 0x19
-#define GLOBAL_MONITOR_CONTROL 0x1a
-#define GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT 12
-#define GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT 8
-#define GLOBAL_MONITOR_CONTROL_ARP_SHIFT 4
-#define GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT 0
-#define GLOBAL_MONITOR_CONTROL_ARP_DISABLED (0xf0)
-#define GLOBAL_CONTROL_2 0x1c
-#define GLOBAL_CONTROL_2_NO_CASCADE 0xe000
-#define GLOBAL_CONTROL_2_MULTIPLE_CASCADE 0xf000
-
-#define GLOBAL_STATS_OP 0x1d
-#define GLOBAL_STATS_OP_BUSY BIT(15)
-#define GLOBAL_STATS_OP_NOP (0 << 12)
-#define GLOBAL_STATS_OP_FLUSH_ALL ((1 << 12) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_FLUSH_PORT ((2 << 12) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_READ_CAPTURED ((4 << 12) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_CAPTURE_PORT ((5 << 12) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_HIST_RX ((1 << 10) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_HIST_TX ((2 << 10) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_HIST_RX_TX ((3 << 10) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_BANK_1 BIT(9)
-#define GLOBAL_STATS_COUNTER_32 0x1e
-#define GLOBAL_STATS_COUNTER_01 0x1f
-
-#define REG_GLOBAL2 0x1c
-#define GLOBAL2_INT_SOURCE 0x00
-#define GLOBAL2_INT_MASK 0x01
-#define GLOBAL2_MGMT_EN_2X 0x02
-#define GLOBAL2_MGMT_EN_0X 0x03
-#define GLOBAL2_FLOW_CONTROL 0x04
-#define GLOBAL2_SWITCH_MGMT 0x05
-#define GLOBAL2_SWITCH_MGMT_USE_DOUBLE_TAG_DATA BIT(15)
-#define GLOBAL2_SWITCH_MGMT_PREVENT_LOOPS BIT(14)
-#define GLOBAL2_SWITCH_MGMT_FLOW_CONTROL_MSG BIT(13)
-#define GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI BIT(7)
-#define GLOBAL2_SWITCH_MGMT_RSVD2CPU BIT(3)
-#define GLOBAL2_DEVICE_MAPPING 0x06
-#define GLOBAL2_DEVICE_MAPPING_UPDATE BIT(15)
-#define GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT 8
-#define GLOBAL2_DEVICE_MAPPING_PORT_MASK 0x0f
-#define GLOBAL2_TRUNK_MASK 0x07
-#define GLOBAL2_TRUNK_MASK_UPDATE BIT(15)
-#define GLOBAL2_TRUNK_MASK_NUM_SHIFT 12
-#define GLOBAL2_TRUNK_MAPPING 0x08
-#define GLOBAL2_TRUNK_MAPPING_UPDATE BIT(15)
-#define GLOBAL2_TRUNK_MAPPING_ID_SHIFT 11
-#define GLOBAL2_INGRESS_OP 0x09
-#define GLOBAL2_INGRESS_DATA 0x0a
-#define GLOBAL2_PVT_ADDR 0x0b
-#define GLOBAL2_PVT_DATA 0x0c
-#define GLOBAL2_SWITCH_MAC 0x0d
-#define GLOBAL2_SWITCH_MAC_BUSY BIT(15)
-#define GLOBAL2_ATU_STATS 0x0e
-#define GLOBAL2_PRIO_OVERRIDE 0x0f
-#define GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP BIT(7)
-#define GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT 4
-#define GLOBAL2_PRIO_OVERRIDE_FORCE_ARP BIT(3)
-#define GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT 0
-#define GLOBAL2_EEPROM_OP 0x14
-#define GLOBAL2_EEPROM_OP_BUSY BIT(15)
-#define GLOBAL2_EEPROM_OP_WRITE ((3 << 12) | GLOBAL2_EEPROM_OP_BUSY)
-#define GLOBAL2_EEPROM_OP_READ ((4 << 12) | GLOBAL2_EEPROM_OP_BUSY)
-#define GLOBAL2_EEPROM_OP_LOAD BIT(11)
-#define GLOBAL2_EEPROM_OP_WRITE_EN BIT(10)
-#define GLOBAL2_EEPROM_OP_ADDR_MASK 0xff
-#define GLOBAL2_EEPROM_DATA 0x15
-#define GLOBAL2_PTP_AVB_OP 0x16
-#define GLOBAL2_PTP_AVB_DATA 0x17
-#define GLOBAL2_SMI_OP 0x18
-#define GLOBAL2_SMI_OP_BUSY BIT(15)
-#define GLOBAL2_SMI_OP_CLAUSE_22 BIT(12)
-#define GLOBAL2_SMI_OP_22_WRITE ((1 << 10) | GLOBAL2_SMI_OP_BUSY | \
- GLOBAL2_SMI_OP_CLAUSE_22)
-#define GLOBAL2_SMI_OP_22_READ ((2 << 10) | GLOBAL2_SMI_OP_BUSY | \
- GLOBAL2_SMI_OP_CLAUSE_22)
-#define GLOBAL2_SMI_OP_45_WRITE_ADDR ((0 << 10) | GLOBAL2_SMI_OP_BUSY)
-#define GLOBAL2_SMI_OP_45_WRITE_DATA ((1 << 10) | GLOBAL2_SMI_OP_BUSY)
-#define GLOBAL2_SMI_OP_45_READ_DATA ((2 << 10) | GLOBAL2_SMI_OP_BUSY)
-#define GLOBAL2_SMI_DATA 0x19
-#define GLOBAL2_SCRATCH_MISC 0x1a
-#define GLOBAL2_SCRATCH_BUSY BIT(15)
-#define GLOBAL2_SCRATCH_REGISTER_SHIFT 8
-#define GLOBAL2_SCRATCH_VALUE_MASK 0xff
-#define GLOBAL2_WDOG_CONTROL 0x1b
-#define GLOBAL2_QOS_WEIGHT 0x1c
-#define GLOBAL2_MISC 0x1d
-
-#define MV88E6XXX_N_FID 4096
-
-/* List of supported models */
-enum mv88e6xxx_model {
- MV88E6085,
- MV88E6095,
- MV88E6123,
- MV88E6131,
- MV88E6161,
- MV88E6165,
- MV88E6171,
- MV88E6172,
- MV88E6175,
- MV88E6176,
- MV88E6185,
- MV88E6240,
- MV88E6320,
- MV88E6321,
- MV88E6350,
- MV88E6351,
- MV88E6352,
-};
-
-enum mv88e6xxx_family {
- MV88E6XXX_FAMILY_NONE,
- MV88E6XXX_FAMILY_6065, /* 6031 6035 6061 6065 */
- MV88E6XXX_FAMILY_6095, /* 6092 6095 */
- MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */
- MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
- MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
- MV88E6XXX_FAMILY_6320, /* 6320 6321 */
- MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
- MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
-};
-
-enum mv88e6xxx_cap {
- /* Address Translation Unit.
- * The ATU is used to lookup and learn MAC addresses. See GLOBAL_ATU_OP.
- */
- MV88E6XXX_CAP_ATU,
-
- /* Energy Efficient Ethernet.
- */
- MV88E6XXX_CAP_EEE,
-
- /* EEPROM Command and Data registers.
- * See GLOBAL2_EEPROM_OP and GLOBAL2_EEPROM_DATA.
- */
- MV88E6XXX_CAP_EEPROM,
-
- /* Port State Filtering for 802.1D Spanning Tree.
- * See PORT_CONTROL_STATE_* values in the PORT_CONTROL register.
- */
- MV88E6XXX_CAP_PORTSTATE,
-
- /* PHY Polling Unit.
- * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
- */
- MV88E6XXX_CAP_PPU,
- MV88E6XXX_CAP_PPU_ACTIVE,
-
- /* SMI PHY Command and Data registers.
- * This requires an indirect access to PHY registers through
- * GLOBAL2_SMI_OP, otherwise direct access to PHY registers is done.
- */
- MV88E6XXX_CAP_SMI_PHY,
-
- /* Per VLAN Spanning Tree Unit (STU).
- * The Port State database, if present, is accessed through VTU
- * operations and dedicated SID registers. See GLOBAL_VTU_SID.
- */
- MV88E6XXX_CAP_STU,
-
- /* Switch MAC/WoL/WoF register.
- * This requires an indirect access to set the switch MAC address
- * through GLOBAL2_SWITCH_MAC, otherwise GLOBAL_MAC_01, GLOBAL_MAC_23,
- * and GLOBAL_MAC_45 are used with a direct access.
- */
- MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF,
-
- /* Internal temperature sensor.
- * Available from any enabled port's PHY register 26, page 6.
- */
- MV88E6XXX_CAP_TEMP,
- MV88E6XXX_CAP_TEMP_LIMIT,
-
- /* In-chip Port Based VLANs.
- * Each port VLANTable register (see PORT_BASE_VLAN) is used to restrict
- * the output (or egress) ports to which it is allowed to send frames.
- */
- MV88E6XXX_CAP_VLANTABLE,
-
- /* VLAN Table Unit.
- * The VTU is used to program 802.1Q VLANs. See GLOBAL_VTU_OP.
- */
- MV88E6XXX_CAP_VTU,
-};
-
-/* Bitmask of capabilities */
-#define MV88E6XXX_FLAG_ATU BIT(MV88E6XXX_CAP_ATU)
-#define MV88E6XXX_FLAG_EEE BIT(MV88E6XXX_CAP_EEE)
-#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
-#define MV88E6XXX_FLAG_PORTSTATE BIT(MV88E6XXX_CAP_PORTSTATE)
-#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
-#define MV88E6XXX_FLAG_PPU_ACTIVE BIT(MV88E6XXX_CAP_PPU_ACTIVE)
-#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
-#define MV88E6XXX_FLAG_STU BIT(MV88E6XXX_CAP_STU)
-#define MV88E6XXX_FLAG_SWITCH_MAC BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF)
-#define MV88E6XXX_FLAG_TEMP BIT(MV88E6XXX_CAP_TEMP)
-#define MV88E6XXX_FLAG_TEMP_LIMIT BIT(MV88E6XXX_CAP_TEMP_LIMIT)
-#define MV88E6XXX_FLAG_VLANTABLE BIT(MV88E6XXX_CAP_VLANTABLE)
-#define MV88E6XXX_FLAG_VTU BIT(MV88E6XXX_CAP_VTU)
-
-#define MV88E6XXX_FLAGS_FAMILY_6095 \
- (MV88E6XXX_FLAG_ATU | \
- MV88E6XXX_FLAG_PPU | \
- MV88E6XXX_FLAG_VLANTABLE | \
- MV88E6XXX_FLAG_VTU)
-
-#define MV88E6XXX_FLAGS_FAMILY_6097 \
- (MV88E6XXX_FLAG_ATU | \
- MV88E6XXX_FLAG_PPU | \
- MV88E6XXX_FLAG_STU | \
- MV88E6XXX_FLAG_VLANTABLE | \
- MV88E6XXX_FLAG_VTU)
-
-#define MV88E6XXX_FLAGS_FAMILY_6165 \
- (MV88E6XXX_FLAG_STU | \
- MV88E6XXX_FLAG_SWITCH_MAC | \
- MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_VTU)
-
-#define MV88E6XXX_FLAGS_FAMILY_6185 \
- (MV88E6XXX_FLAG_ATU | \
- MV88E6XXX_FLAG_PPU | \
- MV88E6XXX_FLAG_VLANTABLE | \
- MV88E6XXX_FLAG_VTU)
-
-#define MV88E6XXX_FLAGS_FAMILY_6320 \
- (MV88E6XXX_FLAG_ATU | \
- MV88E6XXX_FLAG_EEE | \
- MV88E6XXX_FLAG_EEPROM | \
- MV88E6XXX_FLAG_PORTSTATE | \
- MV88E6XXX_FLAG_PPU_ACTIVE | \
- MV88E6XXX_FLAG_SMI_PHY | \
- MV88E6XXX_FLAG_SWITCH_MAC | \
- MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_TEMP_LIMIT | \
- MV88E6XXX_FLAG_VLANTABLE | \
- MV88E6XXX_FLAG_VTU)
-
-#define MV88E6XXX_FLAGS_FAMILY_6351 \
- (MV88E6XXX_FLAG_ATU | \
- MV88E6XXX_FLAG_PORTSTATE | \
- MV88E6XXX_FLAG_PPU_ACTIVE | \
- MV88E6XXX_FLAG_SMI_PHY | \
- MV88E6XXX_FLAG_STU | \
- MV88E6XXX_FLAG_SWITCH_MAC | \
- MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_VLANTABLE | \
- MV88E6XXX_FLAG_VTU)
-
-#define MV88E6XXX_FLAGS_FAMILY_6352 \
- (MV88E6XXX_FLAG_ATU | \
- MV88E6XXX_FLAG_EEE | \
- MV88E6XXX_FLAG_EEPROM | \
- MV88E6XXX_FLAG_PORTSTATE | \
- MV88E6XXX_FLAG_PPU_ACTIVE | \
- MV88E6XXX_FLAG_SMI_PHY | \
- MV88E6XXX_FLAG_STU | \
- MV88E6XXX_FLAG_SWITCH_MAC | \
- MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_TEMP_LIMIT | \
- MV88E6XXX_FLAG_VLANTABLE | \
- MV88E6XXX_FLAG_VTU)
-
-struct mv88e6xxx_info {
- enum mv88e6xxx_family family;
- u16 prod_num;
- const char *name;
- unsigned int num_databases;
- unsigned int num_ports;
- unsigned long flags;
-};
-
-struct mv88e6xxx_atu_entry {
- u16 fid;
- u8 state;
- bool trunk;
- u16 portv_trunkid;
- u8 mac[ETH_ALEN];
-};
-
-struct mv88e6xxx_vtu_stu_entry {
- /* VTU only */
- u16 vid;
- u16 fid;
-
- /* VTU and STU */
- u8 sid;
- bool valid;
- u8 data[DSA_MAX_PORTS];
-};
-
-struct mv88e6xxx_priv_port {
- struct net_device *bridge_dev;
-};
-
-struct mv88e6xxx_priv_state {
- const struct mv88e6xxx_info *info;
-
- /* The dsa_switch this private structure is related to */
- struct dsa_switch *ds;
-
- /* The device this structure is associated to */
- struct device *dev;
-
- /* When using multi-chip addressing, this mutex protects
- * access to the indirect access registers. (In single-chip
- * mode, this mutex is effectively useless.)
- */
- struct mutex smi_mutex;
-
- /* The MII bus and the address on the bus that is used to
- * communication with the switch
- */
- struct mii_bus *bus;
- int sw_addr;
-
- /* Handles automatic disabling and re-enabling of the PHY
- * polling unit.
- */
- struct mutex ppu_mutex;
- int ppu_disabled;
- struct work_struct ppu_work;
- struct timer_list ppu_timer;
-
- /* This mutex serialises access to the statistics unit.
- * Hold this mutex over snapshot + dump sequences.
- */
- struct mutex stats_mutex;
-
- /* This mutex serializes phy access for chips with
- * indirect phy addressing. It is unused for chips
- * with direct phy access.
- */
- struct mutex phy_mutex;
-
- /* This mutex serializes eeprom access for chips with
- * eeprom support.
- */
- struct mutex eeprom_mutex;
-
- struct mv88e6xxx_priv_port ports[DSA_MAX_PORTS];
-
- /* A switch may have a GPIO line tied to its reset pin. Parse
- * this from the device tree, and use it before performing
- * switch soft reset.
- */
- struct gpio_desc *reset;
-
- /* set to size of eeprom if supported by the switch */
- int eeprom_len;
-};
-
-enum stat_type {
- BANK0,
- BANK1,
- PORT,
-};
-
-struct mv88e6xxx_hw_stat {
- char string[ETH_GSTRING_LEN];
- int sizeof_stat;
- int reg;
- enum stat_type type;
-};
-
-static inline bool mv88e6xxx_has(struct mv88e6xxx_priv_state *ps,
- unsigned long flags)
-{
- return (ps->info->flags & flags) == flags;
-}
-
-#endif
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ppm.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ppm.c
deleted file mode 100644
index d88a7a7b2..000000000
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ppm.c
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * cxgb4_ppm.c: Chelsio common library for T4/T5 iSCSI PagePod Manager
- *
- * Copyright (c) 2016 Chelsio Communications, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/kernel.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/debugfs.h>
-#include <linux/export.h>
-#include <linux/list.h>
-#include <linux/skbuff.h>
-#include <linux/pci.h>
-#include <linux/scatterlist.h>
-
-#include "cxgb4_ppm.h"
-
-/* Direct Data Placement -
- * Directly place the iSCSI Data-In or Data-Out PDU's payload into
- * pre-posted final destination host-memory buffers based on the
- * Initiator Task Tag (ITT) in Data-In or Target Task Tag (TTT)
- * in Data-Out PDUs. The host memory address is programmed into
- * h/w in the format of pagepod entries. The location of the
- * pagepod entry is encoded into ddp tag which is used as the base
- * for ITT/TTT.
- */
-
-/* Direct-Data Placement page size adjustment
- */
-int cxgbi_ppm_find_page_index(struct cxgbi_ppm *ppm, unsigned long pgsz)
-{
- struct cxgbi_tag_format *tformat = &ppm->tformat;
- int i;
-
- for (i = 0; i < DDP_PGIDX_MAX; i++) {
- if (pgsz == 1UL << (DDP_PGSZ_BASE_SHIFT +
- tformat->pgsz_order[i])) {
- pr_debug("%s: %s ppm, pgsz %lu -> idx %d.\n",
- __func__, ppm->ndev->name, pgsz, i);
- return i;
- }
- }
- pr_info("ippm: ddp page size %lu not supported.\n", pgsz);
- return DDP_PGIDX_MAX;
-}
-
-/* DDP setup & teardown
- */
-static int ppm_find_unused_entries(unsigned long *bmap,
- unsigned int max_ppods,
- unsigned int start,
- unsigned int nr,
- unsigned int align_mask)
-{
- unsigned long i;
-
- i = bitmap_find_next_zero_area(bmap, max_ppods, start, nr, align_mask);
-
- if (unlikely(i >= max_ppods) && (start > nr))
- i = bitmap_find_next_zero_area(bmap, max_ppods, 0, start - 1,
- align_mask);
- if (unlikely(i >= max_ppods))
- return -ENOSPC;
-
- bitmap_set(bmap, i, nr);
- return (int)i;
-}
-
-static void ppm_mark_entries(struct cxgbi_ppm *ppm, int i, int count,
- unsigned long caller_data)
-{
- struct cxgbi_ppod_data *pdata = ppm->ppod_data + i;
-
- pdata->caller_data = caller_data;
- pdata->npods = count;
-
- if (pdata->color == ((1 << PPOD_IDX_SHIFT) - 1))
- pdata->color = 0;
- else
- pdata->color++;
-}
-
-static int ppm_get_cpu_entries(struct cxgbi_ppm *ppm, unsigned int count,
- unsigned long caller_data)
-{
- struct cxgbi_ppm_pool *pool;
- unsigned int cpu;
- int i;
-
- cpu = get_cpu();
- pool = per_cpu_ptr(ppm->pool, cpu);
- spin_lock_bh(&pool->lock);
- put_cpu();
-
- i = ppm_find_unused_entries(pool->bmap, ppm->pool_index_max,
- pool->next, count, 0);
- if (i < 0) {
- pool->next = 0;
- spin_unlock_bh(&pool->lock);
- return -ENOSPC;
- }
-
- pool->next = i + count;
- if (pool->next >= ppm->pool_index_max)
- pool->next = 0;
-
- spin_unlock_bh(&pool->lock);
-
- pr_debug("%s: cpu %u, idx %d + %d (%d), next %u.\n",
- __func__, cpu, i, count, i + cpu * ppm->pool_index_max,
- pool->next);
-
- i += cpu * ppm->pool_index_max;
- ppm_mark_entries(ppm, i, count, caller_data);
-
- return i;
-}
-
-static int ppm_get_entries(struct cxgbi_ppm *ppm, unsigned int count,
- unsigned long caller_data)
-{
- int i;
-
- spin_lock_bh(&ppm->map_lock);
- i = ppm_find_unused_entries(ppm->ppod_bmap, ppm->bmap_index_max,
- ppm->next, count, 0);
- if (i < 0) {
- ppm->next = 0;
- spin_unlock_bh(&ppm->map_lock);
- pr_debug("ippm: NO suitable entries %u available.\n",
- count);
- return -ENOSPC;
- }
-
- ppm->next = i + count;
- if (ppm->next >= ppm->bmap_index_max)
- ppm->next = 0;
-
- spin_unlock_bh(&ppm->map_lock);
-
- pr_debug("%s: idx %d + %d (%d), next %u, caller_data 0x%lx.\n",
- __func__, i, count, i + ppm->pool_rsvd, ppm->next,
- caller_data);
-
- i += ppm->pool_rsvd;
- ppm_mark_entries(ppm, i, count, caller_data);
-
- return i;
-}
-
-static void ppm_unmark_entries(struct cxgbi_ppm *ppm, int i, int count)
-{
- pr_debug("%s: idx %d + %d.\n", __func__, i, count);
-
- if (i < ppm->pool_rsvd) {
- unsigned int cpu;
- struct cxgbi_ppm_pool *pool;
-
- cpu = i / ppm->pool_index_max;
- i %= ppm->pool_index_max;
-
- pool = per_cpu_ptr(ppm->pool, cpu);
- spin_lock_bh(&pool->lock);
- bitmap_clear(pool->bmap, i, count);
-
- if (i < pool->next)
- pool->next = i;
- spin_unlock_bh(&pool->lock);
-
- pr_debug("%s: cpu %u, idx %d, next %u.\n",
- __func__, cpu, i, pool->next);
- } else {
- spin_lock_bh(&ppm->map_lock);
-
- i -= ppm->pool_rsvd;
- bitmap_clear(ppm->ppod_bmap, i, count);
-
- if (i < ppm->next)
- ppm->next = i;
- spin_unlock_bh(&ppm->map_lock);
-
- pr_debug("%s: idx %d, next %u.\n", __func__, i, ppm->next);
- }
-}
-
-void cxgbi_ppm_ppod_release(struct cxgbi_ppm *ppm, u32 idx)
-{
- struct cxgbi_ppod_data *pdata;
-
- if (idx >= ppm->ppmax) {
- pr_warn("ippm: idx too big %u > %u.\n", idx, ppm->ppmax);
- return;
- }
-
- pdata = ppm->ppod_data + idx;
- if (!pdata->npods) {
- pr_warn("ippm: idx %u, npods 0.\n", idx);
- return;
- }
-
- pr_debug("release idx %u, npods %u.\n", idx, pdata->npods);
- ppm_unmark_entries(ppm, idx, pdata->npods);
-}
-EXPORT_SYMBOL(cxgbi_ppm_ppod_release);
-
-int cxgbi_ppm_ppods_reserve(struct cxgbi_ppm *ppm, unsigned short nr_pages,
- u32 per_tag_pg_idx, u32 *ppod_idx,
- u32 *ddp_tag, unsigned long caller_data)
-{
- struct cxgbi_ppod_data *pdata;
- unsigned int npods;
- int idx = -1;
- unsigned int hwidx;
- u32 tag;
-
- npods = (nr_pages + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
- if (!npods) {
- pr_warn("%s: pages %u -> npods %u, full.\n",
- __func__, nr_pages, npods);
- return -EINVAL;
- }
-
- /* grab from cpu pool first */
- idx = ppm_get_cpu_entries(ppm, npods, caller_data);
- /* try the general pool */
- if (idx < 0)
- idx = ppm_get_entries(ppm, npods, caller_data);
- if (idx < 0) {
- pr_debug("ippm: pages %u, nospc %u, nxt %u, 0x%lx.\n",
- nr_pages, npods, ppm->next, caller_data);
- return idx;
- }
-
- pdata = ppm->ppod_data + idx;
- hwidx = ppm->base_idx + idx;
-
- tag = cxgbi_ppm_make_ddp_tag(hwidx, pdata->color);
-
- if (per_tag_pg_idx)
- tag |= (per_tag_pg_idx << 30) & 0xC0000000;
-
- *ppod_idx = idx;
- *ddp_tag = tag;
-
- pr_debug("ippm: sg %u, tag 0x%x(%u,%u), data 0x%lx.\n",
- nr_pages, tag, idx, npods, caller_data);
-
- return npods;
-}
-EXPORT_SYMBOL(cxgbi_ppm_ppods_reserve);
-
-void cxgbi_ppm_make_ppod_hdr(struct cxgbi_ppm *ppm, u32 tag,
- unsigned int tid, unsigned int offset,
- unsigned int length,
- struct cxgbi_pagepod_hdr *hdr)
-{
- /* The ddp tag in pagepod should be with bit 31:30 set to 0.
- * The ddp Tag on the wire should be with non-zero 31:30 to the peer
- */
- tag &= 0x3FFFFFFF;
-
- hdr->vld_tid = htonl(PPOD_VALID_FLAG | PPOD_TID(tid));
-
- hdr->rsvd = 0;
- hdr->pgsz_tag_clr = htonl(tag & ppm->tformat.idx_clr_mask);
- hdr->max_offset = htonl(length);
- hdr->page_offset = htonl(offset);
-
- pr_debug("ippm: tag 0x%x, tid 0x%x, xfer %u, off %u.\n",
- tag, tid, length, offset);
-}
-EXPORT_SYMBOL(cxgbi_ppm_make_ppod_hdr);
-
-static void ppm_free(struct cxgbi_ppm *ppm)
-{
- vfree(ppm);
-}
-
-static void ppm_destroy(struct kref *kref)
-{
- struct cxgbi_ppm *ppm = container_of(kref,
- struct cxgbi_ppm,
- refcnt);
- pr_info("ippm: kref 0, destroy %s ppm 0x%p.\n",
- ppm->ndev->name, ppm);
-
- *ppm->ppm_pp = NULL;
-
- free_percpu(ppm->pool);
- ppm_free(ppm);
-}
-
-int cxgbi_ppm_release(struct cxgbi_ppm *ppm)
-{
- if (ppm) {
- int rv;
-
- rv = kref_put(&ppm->refcnt, ppm_destroy);
- return rv;
- }
- return 1;
-}
-
-static struct cxgbi_ppm_pool *ppm_alloc_cpu_pool(unsigned int *total,
- unsigned int *pcpu_ppmax)
-{
- struct cxgbi_ppm_pool *pools;
- unsigned int ppmax = (*total) / num_possible_cpus();
- unsigned int max = (PCPU_MIN_UNIT_SIZE - sizeof(*pools)) << 3;
- unsigned int bmap;
- unsigned int alloc_sz;
- unsigned int count = 0;
- unsigned int cpu;
-
- /* make sure per cpu pool fits into PCPU_MIN_UNIT_SIZE */
- if (ppmax > max)
- ppmax = max;
-
- /* pool size must be multiple of unsigned long */
- bmap = BITS_TO_LONGS(ppmax);
- ppmax = (bmap * sizeof(unsigned long)) << 3;
-
- alloc_sz = sizeof(*pools) + sizeof(unsigned long) * bmap;
- pools = __alloc_percpu(alloc_sz, __alignof__(struct cxgbi_ppm_pool));
-
- if (!pools)
- return NULL;
-
- for_each_possible_cpu(cpu) {
- struct cxgbi_ppm_pool *ppool = per_cpu_ptr(pools, cpu);
-
- memset(ppool, 0, alloc_sz);
- spin_lock_init(&ppool->lock);
- count += ppmax;
- }
-
- *total = count;
- *pcpu_ppmax = ppmax;
-
- return pools;
-}
-
-int cxgbi_ppm_init(void **ppm_pp, struct net_device *ndev,
- struct pci_dev *pdev, void *lldev,
- struct cxgbi_tag_format *tformat,
- unsigned int ppmax,
- unsigned int llimit,
- unsigned int start,
- unsigned int reserve_factor)
-{
- struct cxgbi_ppm *ppm = (struct cxgbi_ppm *)(*ppm_pp);
- struct cxgbi_ppm_pool *pool = NULL;
- unsigned int ppmax_pool = 0;
- unsigned int pool_index_max = 0;
- unsigned int alloc_sz;
- unsigned int ppod_bmap_size;
-
- if (ppm) {
- pr_info("ippm: %s, ppm 0x%p,0x%p already initialized, %u/%u.\n",
- ndev->name, ppm_pp, ppm, ppm->ppmax, ppmax);
- kref_get(&ppm->refcnt);
- return 1;
- }
-
- if (reserve_factor) {
- ppmax_pool = ppmax / reserve_factor;
- pool = ppm_alloc_cpu_pool(&ppmax_pool, &pool_index_max);
-
- pr_debug("%s: ppmax %u, cpu total %u, per cpu %u.\n",
- ndev->name, ppmax, ppmax_pool, pool_index_max);
- }
-
- ppod_bmap_size = BITS_TO_LONGS(ppmax - ppmax_pool);
- alloc_sz = sizeof(struct cxgbi_ppm) +
- ppmax * (sizeof(struct cxgbi_ppod_data)) +
- ppod_bmap_size * sizeof(unsigned long);
-
- ppm = vmalloc(alloc_sz);
- if (!ppm)
- goto release_ppm_pool;
-
- memset(ppm, 0, alloc_sz);
-
- ppm->ppod_bmap = (unsigned long *)(&ppm->ppod_data[ppmax]);
-
- if ((ppod_bmap_size >> 3) > (ppmax - ppmax_pool)) {
- unsigned int start = ppmax - ppmax_pool;
- unsigned int end = ppod_bmap_size >> 3;
-
- bitmap_set(ppm->ppod_bmap, ppmax, end - start);
- pr_info("%s: %u - %u < %u * 8, mask extra bits %u, %u.\n",
- __func__, ppmax, ppmax_pool, ppod_bmap_size, start,
- end);
- }
-
- spin_lock_init(&ppm->map_lock);
- kref_init(&ppm->refcnt);
-
- memcpy(&ppm->tformat, tformat, sizeof(struct cxgbi_tag_format));
-
- ppm->ppm_pp = ppm_pp;
- ppm->ndev = ndev;
- ppm->pdev = pdev;
- ppm->lldev = lldev;
- ppm->ppmax = ppmax;
- ppm->next = 0;
- ppm->llimit = llimit;
- ppm->base_idx = start > llimit ?
- (start - llimit + 1) >> PPOD_SIZE_SHIFT : 0;
- ppm->bmap_index_max = ppmax - ppmax_pool;
-
- ppm->pool = pool;
- ppm->pool_rsvd = ppmax_pool;
- ppm->pool_index_max = pool_index_max;
-
- /* check one more time */
- if (*ppm_pp) {
- ppm_free(ppm);
- ppm = (struct cxgbi_ppm *)(*ppm_pp);
-
- pr_info("ippm: %s, ppm 0x%p,0x%p already initialized, %u/%u.\n",
- ndev->name, ppm_pp, *ppm_pp, ppm->ppmax, ppmax);
-
- kref_get(&ppm->refcnt);
- return 1;
- }
- *ppm_pp = ppm;
-
- ppm->tformat.pgsz_idx_dflt = cxgbi_ppm_find_page_index(ppm, PAGE_SIZE);
-
- pr_info("ippm %s: ppm 0x%p, 0x%p, base %u/%u, pg %lu,%u, rsvd %u,%u.\n",
- ndev->name, ppm_pp, ppm, ppm->base_idx, ppm->ppmax, PAGE_SIZE,
- ppm->tformat.pgsz_idx_dflt, ppm->pool_rsvd,
- ppm->pool_index_max);
-
- return 0;
-
-release_ppm_pool:
- free_percpu(pool);
- return -ENOMEM;
-}
-EXPORT_SYMBOL(cxgbi_ppm_init);
-
-unsigned int cxgbi_tagmask_set(unsigned int ppmax)
-{
- unsigned int bits = fls(ppmax);
-
- if (bits > PPOD_IDX_MAX_SIZE)
- bits = PPOD_IDX_MAX_SIZE;
-
- pr_info("ippm: ppmax %u/0x%x -> bits %u, tagmask 0x%x.\n",
- ppmax, ppmax, bits, 1 << (bits + PPOD_IDX_SHIFT));
-
- return 1 << (bits + PPOD_IDX_SHIFT);
-}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ppm.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ppm.h
deleted file mode 100644
index d48732673..000000000
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ppm.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * cxgb4_ppm.h: Chelsio common library for T4/T5 iSCSI ddp operation
- *
- * Copyright (c) 2016 Chelsio Communications, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB4PPM_H__
-#define __CXGB4PPM_H__
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/debugfs.h>
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/scatterlist.h>
-#include <linux/skbuff.h>
-#include <linux/vmalloc.h>
-#include <linux/bitmap.h>
-
-struct cxgbi_pagepod_hdr {
- u32 vld_tid;
- u32 pgsz_tag_clr;
- u32 max_offset;
- u32 page_offset;
- u64 rsvd;
-};
-
-#define PPOD_PAGES_MAX 4
-struct cxgbi_pagepod {
- struct cxgbi_pagepod_hdr hdr;
- u64 addr[PPOD_PAGES_MAX + 1];
-};
-
-/* ddp tag format
- * for a 32-bit tag:
- * bit #
- * 31 ..... ..... 0
- * X Y...Y Z...Z, where
- * ^ ^^^^^ ^^^^
- * | | |____ when ddp bit = 0: color bits
- * | |
- * | |____ when ddp bit = 0: idx into the ddp memory region
- * |
- * |____ ddp bit: 0 - ddp tag, 1 - non-ddp tag
- *
- * [page selector:2] [sw/free bits] [0] [idx] [color:6]
- */
-
-#define DDP_PGIDX_MAX 4
-#define DDP_PGSZ_BASE_SHIFT 12 /* base page 4K */
-
-struct cxgbi_task_tag_info {
- unsigned char flags;
-#define CXGBI_PPOD_INFO_FLAG_VALID 0x1
-#define CXGBI_PPOD_INFO_FLAG_MAPPED 0x2
- unsigned char cid;
- unsigned short pg_shift;
- unsigned int npods;
- unsigned int idx;
- unsigned int tag;
- struct cxgbi_pagepod_hdr hdr;
- int nents;
- int nr_pages;
- struct scatterlist *sgl;
-};
-
-struct cxgbi_tag_format {
- unsigned char pgsz_order[DDP_PGIDX_MAX];
- unsigned char pgsz_idx_dflt;
- unsigned char free_bits:4;
- unsigned char color_bits:4;
- unsigned char idx_bits;
- unsigned char rsvd_bits;
- unsigned int no_ddp_mask;
- unsigned int idx_mask;
- unsigned int color_mask;
- unsigned int idx_clr_mask;
- unsigned int rsvd_mask;
-};
-
-struct cxgbi_ppod_data {
- unsigned char pg_idx:2;
- unsigned char color:6;
- unsigned char chan_id;
- unsigned short npods;
- unsigned long caller_data;
-};
-
-/* per cpu ppm pool */
-struct cxgbi_ppm_pool {
- unsigned int base; /* base index */
- unsigned int next; /* next possible free index */
- spinlock_t lock; /* ppm pool lock */
- unsigned long bmap[0];
-} ____cacheline_aligned_in_smp;
-
-struct cxgbi_ppm {
- struct kref refcnt;
- struct net_device *ndev; /* net_device, 1st port */
- struct pci_dev *pdev;
- void *lldev;
- void **ppm_pp;
- struct cxgbi_tag_format tformat;
- unsigned int ppmax;
- unsigned int llimit;
- unsigned int base_idx;
-
- unsigned int pool_rsvd;
- unsigned int pool_index_max;
- struct cxgbi_ppm_pool __percpu *pool;
- /* map lock */
- spinlock_t map_lock; /* ppm map lock */
- unsigned int bmap_index_max;
- unsigned int next;
- unsigned long *ppod_bmap;
- struct cxgbi_ppod_data ppod_data[0];
-};
-
-#define DDP_THRESHOLD 512
-
-#define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */
-
-#define IPPOD_SIZE sizeof(struct cxgbi_pagepod) /* 64 */
-#define PPOD_SIZE_SHIFT 6
-
-/* page pods are allocated in groups of this size (must be power of 2) */
-#define PPOD_CLUSTER_SIZE 16U
-
-#define ULPMEM_DSGL_MAX_NPPODS 16 /* 1024/PPOD_SIZE */
-#define ULPMEM_IDATA_MAX_NPPODS 3 /* (PPOD_SIZE * 3 + ulptx hdr) < 256B */
-#define PCIE_MEMWIN_MAX_NPPODS 16 /* 1024/PPOD_SIZE */
-
-#define PPOD_COLOR_SHIFT 0
-#define PPOD_COLOR(x) ((x) << PPOD_COLOR_SHIFT)
-
-#define PPOD_IDX_SHIFT 6
-#define PPOD_IDX_MAX_SIZE 24
-
-#define PPOD_TID_SHIFT 0
-#define PPOD_TID(x) ((x) << PPOD_TID_SHIFT)
-
-#define PPOD_TAG_SHIFT 6
-#define PPOD_TAG(x) ((x) << PPOD_TAG_SHIFT)
-
-#define PPOD_VALID_SHIFT 24
-#define PPOD_VALID(x) ((x) << PPOD_VALID_SHIFT)
-#define PPOD_VALID_FLAG PPOD_VALID(1U)
-
-#define PPOD_PI_EXTRACT_CTL_SHIFT 31
-#define PPOD_PI_EXTRACT_CTL(x) ((x) << PPOD_PI_EXTRACT_CTL_SHIFT)
-#define PPOD_PI_EXTRACT_CTL_FLAG V_PPOD_PI_EXTRACT_CTL(1U)
-
-#define PPOD_PI_TYPE_SHIFT 29
-#define PPOD_PI_TYPE_MASK 0x3
-#define PPOD_PI_TYPE(x) ((x) << PPOD_PI_TYPE_SHIFT)
-
-#define PPOD_PI_CHECK_CTL_SHIFT 27
-#define PPOD_PI_CHECK_CTL_MASK 0x3
-#define PPOD_PI_CHECK_CTL(x) ((x) << PPOD_PI_CHECK_CTL_SHIFT)
-
-#define PPOD_PI_REPORT_CTL_SHIFT 25
-#define PPOD_PI_REPORT_CTL_MASK 0x3
-#define PPOD_PI_REPORT_CTL(x) ((x) << PPOD_PI_REPORT_CTL_SHIFT)
-
-static inline int cxgbi_ppm_is_ddp_tag(struct cxgbi_ppm *ppm, u32 tag)
-{
- return !(tag & ppm->tformat.no_ddp_mask);
-}
-
-static inline int cxgbi_ppm_sw_tag_is_usable(struct cxgbi_ppm *ppm,
- u32 tag)
-{
- /* the sw tag must be using <= 31 bits */
- return !(tag & 0x80000000U);
-}
-
-static inline int cxgbi_ppm_make_non_ddp_tag(struct cxgbi_ppm *ppm,
- u32 sw_tag,
- u32 *final_tag)
-{
- struct cxgbi_tag_format *tformat = &ppm->tformat;
-
- if (!cxgbi_ppm_sw_tag_is_usable(ppm, sw_tag)) {
- pr_info("sw_tag 0x%x NOT usable.\n", sw_tag);
- return -EINVAL;
- }
-
- if (!sw_tag) {
- *final_tag = tformat->no_ddp_mask;
- } else {
- unsigned int shift = tformat->idx_bits + tformat->color_bits;
- u32 lower = sw_tag & tformat->idx_clr_mask;
- u32 upper = (sw_tag >> shift) << (shift + 1);
-
- *final_tag = upper | tformat->no_ddp_mask | lower;
- }
- return 0;
-}
-
-static inline u32 cxgbi_ppm_decode_non_ddp_tag(struct cxgbi_ppm *ppm,
- u32 tag)
-{
- struct cxgbi_tag_format *tformat = &ppm->tformat;
- unsigned int shift = tformat->idx_bits + tformat->color_bits;
- u32 lower = tag & tformat->idx_clr_mask;
- u32 upper = (tag >> tformat->rsvd_bits) << shift;
-
- return upper | lower;
-}
-
-static inline u32 cxgbi_ppm_ddp_tag_get_idx(struct cxgbi_ppm *ppm,
- u32 ddp_tag)
-{
- u32 hw_idx = (ddp_tag >> PPOD_IDX_SHIFT) &
- ppm->tformat.idx_mask;
-
- return hw_idx - ppm->base_idx;
-}
-
-static inline u32 cxgbi_ppm_make_ddp_tag(unsigned int hw_idx,
- unsigned char color)
-{
- return (hw_idx << PPOD_IDX_SHIFT) | ((u32)color);
-}
-
-static inline unsigned long
-cxgbi_ppm_get_tag_caller_data(struct cxgbi_ppm *ppm,
- u32 ddp_tag)
-{
- u32 idx = cxgbi_ppm_ddp_tag_get_idx(ppm, ddp_tag);
-
- return ppm->ppod_data[idx].caller_data;
-}
-
-/* sw bits are the free bits */
-static inline int cxgbi_ppm_ddp_tag_update_sw_bits(struct cxgbi_ppm *ppm,
- u32 val, u32 orig_tag,
- u32 *final_tag)
-{
- struct cxgbi_tag_format *tformat = &ppm->tformat;
- u32 v = val >> tformat->free_bits;
-
- if (v) {
- pr_info("sw_bits 0x%x too large, avail bits %u.\n",
- val, tformat->free_bits);
- return -EINVAL;
- }
- if (!cxgbi_ppm_is_ddp_tag(ppm, orig_tag))
- return -EINVAL;
-
- *final_tag = (val << tformat->rsvd_bits) |
- (orig_tag & ppm->tformat.rsvd_mask);
- return 0;
-}
-
-static inline void cxgbi_ppm_ppod_clear(struct cxgbi_pagepod *ppod)
-{
- ppod->hdr.vld_tid = 0U;
-}
-
-static inline void cxgbi_tagmask_check(unsigned int tagmask,
- struct cxgbi_tag_format *tformat)
-{
- unsigned int bits = fls(tagmask);
-
- /* reserve top most 2 bits for page selector */
- tformat->free_bits = 32 - 2 - bits;
- tformat->rsvd_bits = bits;
- tformat->color_bits = PPOD_IDX_SHIFT;
- tformat->idx_bits = bits - 1 - PPOD_IDX_SHIFT;
- tformat->no_ddp_mask = 1 << (bits - 1);
- tformat->idx_mask = (1 << tformat->idx_bits) - 1;
- tformat->color_mask = (1 << PPOD_IDX_SHIFT) - 1;
- tformat->idx_clr_mask = (1 << (bits - 1)) - 1;
- tformat->rsvd_mask = (1 << bits) - 1;
-
- pr_info("ippm: tagmask 0x%x, rsvd %u=%u+%u+1, mask 0x%x,0x%x, "
- "pg %u,%u,%u,%u.\n",
- tagmask, tformat->rsvd_bits, tformat->idx_bits,
- tformat->color_bits, tformat->no_ddp_mask, tformat->rsvd_mask,
- tformat->pgsz_order[0], tformat->pgsz_order[1],
- tformat->pgsz_order[2], tformat->pgsz_order[3]);
-}
-
-int cxgbi_ppm_find_page_index(struct cxgbi_ppm *ppm, unsigned long pgsz);
-void cxgbi_ppm_make_ppod_hdr(struct cxgbi_ppm *ppm, u32 tag,
- unsigned int tid, unsigned int offset,
- unsigned int length,
- struct cxgbi_pagepod_hdr *hdr);
-void cxgbi_ppm_ppod_release(struct cxgbi_ppm *, u32 idx);
-int cxgbi_ppm_ppods_reserve(struct cxgbi_ppm *, unsigned short nr_pages,
- u32 per_tag_pg_idx, u32 *ppod_idx, u32 *ddp_tag,
- unsigned long caller_data);
-int cxgbi_ppm_init(void **ppm_pp, struct net_device *, struct pci_dev *,
- void *lldev, struct cxgbi_tag_format *,
- unsigned int ppmax, unsigned int llimit,
- unsigned int start,
- unsigned int reserve_factor);
-int cxgbi_ppm_release(struct cxgbi_ppm *ppm);
-void cxgbi_tagmask_check(unsigned int tagmask, struct cxgbi_tag_format *);
-unsigned int cxgbi_tagmask_set(unsigned int ppmax);
-
-#endif /*__CXGB4PPM_H__*/
diff --git a/drivers/net/wireless/broadcom/b43/phy_a.c b/drivers/net/wireless/broadcom/b43/phy_a.c
deleted file mode 100644
index 99c036f5e..000000000
--- a/drivers/net/wireless/broadcom/b43/phy_a.c
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
-
- Broadcom B43 wireless driver
- IEEE 802.11a PHY driver
-
- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
- Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
- Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
-
- 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.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
-*/
-
-#include <linux/slab.h>
-
-#include "b43.h"
-#include "phy_a.h"
-#include "phy_common.h"
-#include "wa.h"
-#include "tables.h"
-#include "main.h"
-
-
-/* Get the freq, as it has to be written to the device. */
-static inline u16 channel2freq_a(u8 channel)
-{
- B43_WARN_ON(channel > 200);
-
- return (5000 + 5 * channel);
-}
-
-static inline u16 freq_r3A_value(u16 frequency)
-{
- u16 value;
-
- if (frequency < 5091)
- value = 0x0040;
- else if (frequency < 5321)
- value = 0x0000;
- else if (frequency < 5806)
- value = 0x0080;
- else
- value = 0x0040;
-
- return value;
-}
-
-#if 0
-/* This function converts a TSSI value to dBm in Q5.2 */
-static s8 b43_aphy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
-{
- struct b43_phy *phy = &dev->phy;
- struct b43_phy_a *aphy = phy->a;
- s8 dbm = 0;
- s32 tmp;
-
- tmp = (aphy->tgt_idle_tssi - aphy->cur_idle_tssi + tssi);
- tmp += 0x80;
- tmp = clamp_val(tmp, 0x00, 0xFF);
- dbm = aphy->tssi2dbm[tmp];
- //TODO: There's a FIXME on the specs
-
- return dbm;
-}
-#endif
-
-static void b43_radio_set_tx_iq(struct b43_wldev *dev)
-{
- static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
- static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
- u16 tmp = b43_radio_read16(dev, 0x001E);
- int i, j;
-
- for (i = 0; i < 5; i++) {
- for (j = 0; j < 5; j++) {
- if (tmp == (data_high[i] << 4 | data_low[j])) {
- b43_phy_write(dev, 0x0069,
- (i - j) << 8 | 0x00C0);
- return;
- }
- }
- }
-}
-
-static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
-{
- u16 freq, r8, tmp;
-
- freq = channel2freq_a(channel);
-
- r8 = b43_radio_read16(dev, 0x0008);
- b43_write16(dev, 0x03F0, freq);
- b43_radio_write16(dev, 0x0008, r8);
-
- //TODO: write max channel TX power? to Radio 0x2D
- tmp = b43_radio_read16(dev, 0x002E);
- tmp &= 0x0080;
- //TODO: OR tmp with the Power out estimation for this channel?
- b43_radio_write16(dev, 0x002E, tmp);
-
- if (freq >= 4920 && freq <= 5500) {
- /*
- * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
- * = (freq * 0.025862069
- */
- r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
- }
- b43_radio_write16(dev, 0x0007, (r8 << 4) | r8);
- b43_radio_write16(dev, 0x0020, (r8 << 4) | r8);
- b43_radio_write16(dev, 0x0021, (r8 << 4) | r8);
- b43_radio_maskset(dev, 0x0022, 0x000F, (r8 << 4));
- b43_radio_write16(dev, 0x002A, (r8 << 4));
- b43_radio_write16(dev, 0x002B, (r8 << 4));
- b43_radio_maskset(dev, 0x0008, 0x00F0, (r8 << 4));
- b43_radio_maskset(dev, 0x0029, 0xFF0F, 0x00B0);
- b43_radio_write16(dev, 0x0035, 0x00AA);
- b43_radio_write16(dev, 0x0036, 0x0085);
- b43_radio_maskset(dev, 0x003A, 0xFF20, freq_r3A_value(freq));
- b43_radio_mask(dev, 0x003D, 0x00FF);
- b43_radio_maskset(dev, 0x0081, 0xFF7F, 0x0080);
- b43_radio_mask(dev, 0x0035, 0xFFEF);
- b43_radio_maskset(dev, 0x0035, 0xFFEF, 0x0010);
- b43_radio_set_tx_iq(dev);
- //TODO: TSSI2dbm workaround
-//FIXME b43_phy_xmitpower(dev);
-}
-
-static void b43_radio_init2060(struct b43_wldev *dev)
-{
- b43_radio_write16(dev, 0x0004, 0x00C0);
- b43_radio_write16(dev, 0x0005, 0x0008);
- b43_radio_write16(dev, 0x0009, 0x0040);
- b43_radio_write16(dev, 0x0005, 0x00AA);
- b43_radio_write16(dev, 0x0032, 0x008F);
- b43_radio_write16(dev, 0x0006, 0x008F);
- b43_radio_write16(dev, 0x0034, 0x008F);
- b43_radio_write16(dev, 0x002C, 0x0007);
- b43_radio_write16(dev, 0x0082, 0x0080);
- b43_radio_write16(dev, 0x0080, 0x0000);
- b43_radio_write16(dev, 0x003F, 0x00DA);
- b43_radio_mask(dev, 0x0005, ~0x0008);
- b43_radio_mask(dev, 0x0081, ~0x0010);
- b43_radio_mask(dev, 0x0081, ~0x0020);
- b43_radio_mask(dev, 0x0081, ~0x0020);
- msleep(1); /* delay 400usec */
-
- b43_radio_maskset(dev, 0x0081, ~0x0020, 0x0010);
- msleep(1); /* delay 400usec */
-
- b43_radio_maskset(dev, 0x0005, ~0x0008, 0x0008);
- b43_radio_mask(dev, 0x0085, ~0x0010);
- b43_radio_mask(dev, 0x0005, ~0x0008);
- b43_radio_mask(dev, 0x0081, ~0x0040);
- b43_radio_maskset(dev, 0x0081, ~0x0040, 0x0040);
- b43_radio_write16(dev, 0x0005,
- (b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008);
- b43_phy_write(dev, 0x0063, 0xDDC6);
- b43_phy_write(dev, 0x0069, 0x07BE);
- b43_phy_write(dev, 0x006A, 0x0000);
-
- aphy_channel_switch(dev, dev->phy.ops->get_default_chan(dev));
-
- msleep(1);
-}
-
-static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable)
-{
- int i;
-
- if (dev->phy.rev < 3) {
- if (enable)
- for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8);
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_WRSSI, i, 0xFFF8);
- }
- else
- for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]);
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]);
- }
- } else {
- if (enable)
- for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++)
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_WRSSI, i, 0x0820);
- else
- for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++)
- b43_ofdmtab_write16(dev,
- B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]);
- }
-}
-
-static void b43_phy_ww(struct b43_wldev *dev)
-{
- u16 b, curr_s, best_s = 0xFFFF;
- int i;
-
- b43_phy_mask(dev, B43_PHY_CRS0, ~B43_PHY_CRS0_EN);
- b43_phy_set(dev, B43_PHY_OFDM(0x1B), 0x1000);
- b43_phy_maskset(dev, B43_PHY_OFDM(0x82), 0xF0FF, 0x0300);
- b43_radio_set(dev, 0x0009, 0x0080);
- b43_radio_maskset(dev, 0x0012, 0xFFFC, 0x0002);
- b43_wa_initgains(dev);
- b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5);
- b = b43_phy_read(dev, B43_PHY_PWRDOWN);
- b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005);
- b43_radio_set(dev, 0x0004, 0x0004);
- for (i = 0x10; i <= 0x20; i++) {
- b43_radio_write16(dev, 0x0013, i);
- curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF;
- if (!curr_s) {
- best_s = 0x0000;
- break;
- } else if (curr_s >= 0x0080)
- curr_s = 0x0100 - curr_s;
- if (curr_s < best_s)
- best_s = curr_s;
- }
- b43_phy_write(dev, B43_PHY_PWRDOWN, b);
- b43_radio_mask(dev, 0x0004, 0xFFFB);
- b43_radio_write16(dev, 0x0013, best_s);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC);
- b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80);
- b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00);
- b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0);
- b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0);
- b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF);
- b43_phy_maskset(dev, B43_PHY_OFDM(0xBB), 0xF000, 0x0053);
- b43_phy_maskset(dev, B43_PHY_OFDM61, 0xFE1F, 0x0120);
- b43_phy_maskset(dev, B43_PHY_OFDM(0x13), 0x0FFF, 0x3000);
- b43_phy_maskset(dev, B43_PHY_OFDM(0x14), 0x0FFF, 0x3000);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017);
- for (i = 0; i < 6; i++)
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011);
- b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013);
- b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030);
- b43_phy_set(dev, B43_PHY_CRS0, B43_PHY_CRS0_EN);
-}
-
-static void hardware_pctl_init_aphy(struct b43_wldev *dev)
-{
- //TODO
-}
-
-void b43_phy_inita(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
-
- /* This lowlevel A-PHY init is also called from G-PHY init.
- * So we must not access phy->a, if called from G-PHY code.
- */
- B43_WARN_ON((phy->type != B43_PHYTYPE_A) &&
- (phy->type != B43_PHYTYPE_G));
-
- might_sleep();
-
- if (phy->rev >= 6) {
- if (phy->type == B43_PHYTYPE_A)
- b43_phy_mask(dev, B43_PHY_OFDM(0x1B), ~0x1000);
- if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
- b43_phy_set(dev, B43_PHY_ENCORE, 0x0010);
- else
- b43_phy_mask(dev, B43_PHY_ENCORE, ~0x1010);
- }
-
- b43_wa_all(dev);
-
- if (phy->type == B43_PHYTYPE_A) {
- if (phy->gmode && (phy->rev < 3))
- b43_phy_set(dev, 0x0034, 0x0001);
- b43_phy_rssiagc(dev, 0);
-
- b43_phy_set(dev, B43_PHY_CRS0, B43_PHY_CRS0_EN);
-
- b43_radio_init2060(dev);
-
- if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
- ((dev->dev->board_type == SSB_BOARD_BU4306) ||
- (dev->dev->board_type == SSB_BOARD_BU4309))) {
- ; //TODO: A PHY LO
- }
-
- if (phy->rev >= 3)
- b43_phy_ww(dev);
-
- hardware_pctl_init_aphy(dev);
-
- //TODO: radar detection
- }
-
- if ((phy->type == B43_PHYTYPE_G) &&
- (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)) {
- b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
- }
-}
-
-/* Initialise the TSSI->dBm lookup table */
-static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- struct b43_phy_a *aphy = phy->a;
- s16 pab0, pab1, pab2;
-
- pab0 = (s16) (dev->dev->bus_sprom->pa1b0);
- pab1 = (s16) (dev->dev->bus_sprom->pa1b1);
- pab2 = (s16) (dev->dev->bus_sprom->pa1b2);
-
- if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
- pab0 != -1 && pab1 != -1 && pab2 != -1) {
- /* The pabX values are set in SPROM. Use them. */
- if ((s8) dev->dev->bus_sprom->itssi_a != 0 &&
- (s8) dev->dev->bus_sprom->itssi_a != -1)
- aphy->tgt_idle_tssi =
- (s8) (dev->dev->bus_sprom->itssi_a);
- else
- aphy->tgt_idle_tssi = 62;
- aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
- pab1, pab2);
- if (!aphy->tssi2dbm)
- return -ENOMEM;
- } else {
- /* pabX values not set in SPROM,
- * but APHY needs a generated table. */
- aphy->tssi2dbm = NULL;
- b43err(dev->wl, "Could not generate tssi2dBm "
- "table (wrong SPROM info)!\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int b43_aphy_op_allocate(struct b43_wldev *dev)
-{
- struct b43_phy_a *aphy;
- int err;
-
- aphy = kzalloc(sizeof(*aphy), GFP_KERNEL);
- if (!aphy)
- return -ENOMEM;
- dev->phy.a = aphy;
-
- err = b43_aphy_init_tssi2dbm_table(dev);
- if (err)
- goto err_free_aphy;
-
- return 0;
-
-err_free_aphy:
- kfree(aphy);
- dev->phy.a = NULL;
-
- return err;
-}
-
-static void b43_aphy_op_prepare_structs(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- struct b43_phy_a *aphy = phy->a;
- const void *tssi2dbm;
- int tgt_idle_tssi;
-
- /* tssi2dbm table is constant, so it is initialized at alloc time.
- * Save a copy of the pointer. */
- tssi2dbm = aphy->tssi2dbm;
- tgt_idle_tssi = aphy->tgt_idle_tssi;
-
- /* Zero out the whole PHY structure. */
- memset(aphy, 0, sizeof(*aphy));
-
- aphy->tssi2dbm = tssi2dbm;
- aphy->tgt_idle_tssi = tgt_idle_tssi;
-
- //TODO init struct b43_phy_a
-
-}
-
-static void b43_aphy_op_free(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- struct b43_phy_a *aphy = phy->a;
-
- kfree(aphy->tssi2dbm);
- aphy->tssi2dbm = NULL;
-
- kfree(aphy);
- dev->phy.a = NULL;
-}
-
-static int b43_aphy_op_init(struct b43_wldev *dev)
-{
- b43_phy_inita(dev);
-
- return 0;
-}
-
-static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset)
-{
- /* OFDM registers are base-registers for the A-PHY. */
- if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
- offset &= ~B43_PHYROUTE;
- offset |= B43_PHYROUTE_BASE;
- }
-
-#if B43_DEBUG
- if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
- /* Ext-G registers are only available on G-PHYs */
- b43err(dev->wl, "Invalid EXT-G PHY access at "
- "0x%04X on A-PHY\n", offset);
- dump_stack();
- }
- if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) {
- /* N-BMODE registers are only available on N-PHYs */
- b43err(dev->wl, "Invalid N-BMODE PHY access at "
- "0x%04X on A-PHY\n", offset);
- dump_stack();
- }
-#endif /* B43_DEBUG */
-
- return offset;
-}
-
-static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg)
-{
- reg = adjust_phyreg(dev, reg);
- b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
- return b43_read16(dev, B43_MMIO_PHY_DATA);
-}
-
-static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
-{
- reg = adjust_phyreg(dev, reg);
- b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
- b43_write16(dev, B43_MMIO_PHY_DATA, value);
-}
-
-static u16 b43_aphy_op_radio_read(struct b43_wldev *dev, u16 reg)
-{
- /* Register 1 is a 32-bit register. */
- B43_WARN_ON(reg == 1);
- /* A-PHY needs 0x40 for read access */
- reg |= 0x40;
-
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
- return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
-}
-
-static void b43_aphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
-{
- /* Register 1 is a 32-bit register. */
- B43_WARN_ON(reg == 1);
-
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
- b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
-}
-
-static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev)
-{
- return (dev->phy.rev >= 5);
-}
-
-static void b43_aphy_op_software_rfkill(struct b43_wldev *dev,
- bool blocked)
-{
- struct b43_phy *phy = &dev->phy;
-
- if (!blocked) {
- if (phy->radio_on)
- return;
- b43_radio_write16(dev, 0x0004, 0x00C0);
- b43_radio_write16(dev, 0x0005, 0x0008);
- b43_phy_mask(dev, 0x0010, 0xFFF7);
- b43_phy_mask(dev, 0x0011, 0xFFF7);
- b43_radio_init2060(dev);
- } else {
- b43_radio_write16(dev, 0x0004, 0x00FF);
- b43_radio_write16(dev, 0x0005, 0x00FB);
- b43_phy_set(dev, 0x0010, 0x0008);
- b43_phy_set(dev, 0x0011, 0x0008);
- }
-}
-
-static int b43_aphy_op_switch_channel(struct b43_wldev *dev,
- unsigned int new_channel)
-{
- if (new_channel > 200)
- return -EINVAL;
- aphy_channel_switch(dev, new_channel);
-
- return 0;
-}
-
-static unsigned int b43_aphy_op_get_default_chan(struct b43_wldev *dev)
-{
- return 36; /* Default to channel 36 */
-}
-
-static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
-{//TODO
- struct b43_phy *phy = &dev->phy;
- u16 tmp;
- int autodiv = 0;
-
- if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
- autodiv = 1;
-
- b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
-
- b43_phy_maskset(dev, B43_PHY_BBANDCFG, ~B43_PHY_BBANDCFG_RXANT,
- (autodiv ? B43_ANTENNA_AUTO1 : antenna) <<
- B43_PHY_BBANDCFG_RXANT_SHIFT);
-
- if (autodiv) {
- tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
- if (antenna == B43_ANTENNA_AUTO1)
- tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
- else
- tmp |= B43_PHY_ANTDWELL_AUTODIV1;
- b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
- }
- if (phy->rev < 3)
- b43_phy_maskset(dev, B43_PHY_ANTDWELL, 0xFF00, 0x24);
- else {
- b43_phy_set(dev, B43_PHY_OFDM61, 0x10);
- if (phy->rev == 3) {
- b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, 0x1D);
- b43_phy_write(dev, B43_PHY_ADIVRELATED, 8);
- } else {
- b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, 0x3A);
- b43_phy_maskset(dev, B43_PHY_ADIVRELATED, 0xFF00, 8);
- }
- }
-
- b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
-}
-
-static void b43_aphy_op_adjust_txpower(struct b43_wldev *dev)
-{//TODO
-}
-
-static enum b43_txpwr_result b43_aphy_op_recalc_txpower(struct b43_wldev *dev,
- bool ignore_tssi)
-{//TODO
- return B43_TXPWR_RES_DONE;
-}
-
-static void b43_aphy_op_pwork_15sec(struct b43_wldev *dev)
-{//TODO
-}
-
-static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev)
-{//TODO
-}
-
-static const struct b43_phy_operations b43_phyops_a = {
- .allocate = b43_aphy_op_allocate,
- .free = b43_aphy_op_free,
- .prepare_structs = b43_aphy_op_prepare_structs,
- .init = b43_aphy_op_init,
- .phy_read = b43_aphy_op_read,
- .phy_write = b43_aphy_op_write,
- .radio_read = b43_aphy_op_radio_read,
- .radio_write = b43_aphy_op_radio_write,
- .supports_hwpctl = b43_aphy_op_supports_hwpctl,
- .software_rfkill = b43_aphy_op_software_rfkill,
- .switch_analog = b43_phyop_switch_analog_generic,
- .switch_channel = b43_aphy_op_switch_channel,
- .get_default_chan = b43_aphy_op_get_default_chan,
- .set_rx_antenna = b43_aphy_op_set_rx_antenna,
- .recalc_txpower = b43_aphy_op_recalc_txpower,
- .adjust_txpower = b43_aphy_op_adjust_txpower,
- .pwork_15sec = b43_aphy_op_pwork_15sec,
- .pwork_60sec = b43_aphy_op_pwork_60sec,
-};
diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
deleted file mode 100644
index 9878bebd4..000000000
--- a/drivers/pci/ecam.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2016 Broadcom
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation (the "GPL").
- *
- * 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 version 2 (GPLv2) for more details.
- *
- * You should have received a copy of the GNU General Public License
- * version 2 (GPLv2) along with this source code.
- */
-#ifndef DRIVERS_PCI_ECAM_H
-#define DRIVERS_PCI_ECAM_H
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-/*
- * struct to hold pci ops and bus shift of the config window
- * for a PCI controller.
- */
-struct pci_config_window;
-struct pci_ecam_ops {
- unsigned int bus_shift;
- struct pci_ops pci_ops;
- int (*init)(struct device *,
- struct pci_config_window *);
-};
-
-/*
- * struct to hold the mappings of a config space window. This
- * is expected to be used as sysdata for PCI controllers that
- * use ECAM.
- */
-struct pci_config_window {
- struct resource res;
- struct resource busr;
- void *priv;
- struct pci_ecam_ops *ops;
- union {
- void __iomem *win; /* 64-bit single mapping */
- void __iomem **winp; /* 32-bit per-bus mapping */
- };
-};
-
-/* create and free pci_config_window */
-struct pci_config_window *pci_ecam_create(struct device *dev,
- struct resource *cfgres, struct resource *busr,
- struct pci_ecam_ops *ops);
-void pci_ecam_free(struct pci_config_window *cfg);
-
-/* map_bus when ->sysdata is an instance of pci_config_window */
-void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
- int where);
-/* default ECAM ops */
-extern struct pci_ecam_ops pci_generic_ecam_ops;
-
-#ifdef CONFIG_PCI_HOST_GENERIC
-/* for DT-based PCI controllers that support ECAM */
-int pci_host_common_probe(struct platform_device *pdev,
- struct pci_ecam_ops *ops);
-#endif
-#endif
diff --git a/drivers/pwm/pwm-tipwmss.h b/drivers/pwm/pwm-tipwmss.h
deleted file mode 100644
index 10ad80404..000000000
--- a/drivers/pwm/pwm-tipwmss.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * TI PWM Subsystem driver
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- *
- * 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.
- *
- */
-
-#ifndef __TIPWMSS_H
-#define __TIPWMSS_H
-
-/* PWM substem clock gating */
-#define PWMSS_ECAPCLK_EN BIT(0)
-#define PWMSS_ECAPCLK_STOP_REQ BIT(1)
-#define PWMSS_EPWMCLK_EN BIT(8)
-#define PWMSS_EPWMCLK_STOP_REQ BIT(9)
-
-#define PWMSS_ECAPCLK_EN_ACK BIT(0)
-#define PWMSS_EPWMCLK_EN_ACK BIT(8)
-
-#ifdef CONFIG_PWM_TIPWMSS
-extern u16 pwmss_submodule_state_change(struct device *dev, int set);
-#else
-static inline u16 pwmss_submodule_state_change(struct device *dev, int set)
-{
- /* return success status value */
- return 0xFFFF;
-}
-#endif
-#endif /* __TIPWMSS_H */
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index ec6381e57..258a3f9a2 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -246,10 +246,6 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
shost->dma_dev = dma_dev;
- error = device_add(&shost->shost_gendev);
- if (error)
- goto out_destroy_freelist;
-
/*
* Increase usage count temporarily here so that calling
* scsi_autopm_put_host() will trigger runtime idle if there is
@@ -260,6 +256,10 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
pm_runtime_enable(&shost->shost_gendev);
device_enable_async_suspend(&shost->shost_gendev);
+ error = device_add(&shost->shost_gendev);
+ if (error)
+ goto out_destroy_freelist;
+
scsi_host_set_state(shost, SHOST_RUNNING);
get_device(shost->shost_gendev.parent);
@@ -309,6 +309,10 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
out_del_gendev:
device_del(&shost->shost_gendev);
out_destroy_freelist:
+ device_disable_async_suspend(&shost->shost_gendev);
+ pm_runtime_disable(&shost->shost_gendev);
+ pm_runtime_set_suspended(&shost->shost_gendev);
+ pm_runtime_put_noidle(&shost->shost_gendev);
scsi_destroy_command_freelist(shost);
out_destroy_tags:
if (shost_use_blk_mq(shost))
diff --git a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h
deleted file mode 100644
index c1ab8a4c3..000000000
--- a/drivers/scsi/ibmvscsi/viosrp.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*****************************************************************************/
-/* srp.h -- SCSI RDMA Protocol definitions */
-/* */
-/* Written By: Colin Devilbis, IBM Corporation */
-/* */
-/* Copyright (C) 2003 IBM Corporation */
-/* */
-/* 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. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the Free Software */
-/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* */
-/* */
-/* This file contains structures and definitions for IBM RPA (RS/6000 */
-/* platform architecture) implementation of the SRP (SCSI RDMA Protocol) */
-/* standard. SRP is used on IBM iSeries and pSeries platforms to send SCSI */
-/* commands between logical partitions. */
-/* */
-/* SRP Information Units (IUs) are sent on a "Command/Response Queue" (CRQ) */
-/* between partitions. The definitions in this file are architected, */
-/* and cannot be changed without breaking compatibility with other versions */
-/* of Linux and other operating systems (AIX, OS/400) that talk this protocol*/
-/* between logical partitions */
-/*****************************************************************************/
-#ifndef VIOSRP_H
-#define VIOSRP_H
-#include <scsi/srp.h>
-
-#define SRP_VERSION "16.a"
-#define SRP_MAX_IU_LEN 256
-#define SRP_MAX_LOC_LEN 32
-
-union srp_iu {
- struct srp_login_req login_req;
- struct srp_login_rsp login_rsp;
- struct srp_login_rej login_rej;
- struct srp_i_logout i_logout;
- struct srp_t_logout t_logout;
- struct srp_tsk_mgmt tsk_mgmt;
- struct srp_cmd cmd;
- struct srp_rsp rsp;
- u8 reserved[SRP_MAX_IU_LEN];
-};
-
-enum viosrp_crq_headers {
- VIOSRP_CRQ_FREE = 0x00,
- VIOSRP_CRQ_CMD_RSP = 0x80,
- VIOSRP_CRQ_INIT_RSP = 0xC0,
- VIOSRP_CRQ_XPORT_EVENT = 0xFF
-};
-
-enum viosrp_crq_init_formats {
- VIOSRP_CRQ_INIT = 0x01,
- VIOSRP_CRQ_INIT_COMPLETE = 0x02
-};
-
-enum viosrp_crq_formats {
- VIOSRP_SRP_FORMAT = 0x01,
- VIOSRP_MAD_FORMAT = 0x02,
- VIOSRP_OS400_FORMAT = 0x03,
- VIOSRP_AIX_FORMAT = 0x04,
- VIOSRP_LINUX_FORMAT = 0x05,
- VIOSRP_INLINE_FORMAT = 0x06
-};
-
-enum viosrp_crq_status {
- VIOSRP_OK = 0x0,
- VIOSRP_NONRECOVERABLE_ERR = 0x1,
- VIOSRP_VIOLATES_MAX_XFER = 0x2,
- VIOSRP_PARTNER_PANIC = 0x3,
- VIOSRP_DEVICE_BUSY = 0x8,
- VIOSRP_ADAPTER_FAIL = 0x10,
- VIOSRP_OK2 = 0x99,
-};
-
-struct viosrp_crq {
- u8 valid; /* used by RPA */
- u8 format; /* SCSI vs out-of-band */
- u8 reserved;
- u8 status; /* non-scsi failure? (e.g. DMA failure) */
- __be16 timeout; /* in seconds */
- __be16 IU_length; /* in bytes */
- __be64 IU_data_ptr; /* the TCE for transferring data */
-};
-
-/* MADs are Management requests above and beyond the IUs defined in the SRP
- * standard.
- */
-enum viosrp_mad_types {
- VIOSRP_EMPTY_IU_TYPE = 0x01,
- VIOSRP_ERROR_LOG_TYPE = 0x02,
- VIOSRP_ADAPTER_INFO_TYPE = 0x03,
- VIOSRP_CAPABILITIES_TYPE = 0x05,
- VIOSRP_ENABLE_FAST_FAIL = 0x08,
-};
-
-enum viosrp_mad_status {
- VIOSRP_MAD_SUCCESS = 0x00,
- VIOSRP_MAD_NOT_SUPPORTED = 0xF1,
- VIOSRP_MAD_FAILED = 0xF7,
-};
-
-enum viosrp_capability_type {
- MIGRATION_CAPABILITIES = 0x01,
- RESERVATION_CAPABILITIES = 0x02,
-};
-
-enum viosrp_capability_support {
- SERVER_DOES_NOT_SUPPORTS_CAP = 0x0,
- SERVER_SUPPORTS_CAP = 0x01,
- SERVER_CAP_DATA = 0x02,
-};
-
-enum viosrp_reserve_type {
- CLIENT_RESERVE_SCSI_2 = 0x01,
-};
-
-enum viosrp_capability_flag {
- CLIENT_MIGRATED = 0x01,
- CLIENT_RECONNECT = 0x02,
- CAP_LIST_SUPPORTED = 0x04,
- CAP_LIST_DATA = 0x08,
-};
-
-/*
- * Common MAD header
- */
-struct mad_common {
- __be32 type;
- __be16 status;
- __be16 length;
- __be64 tag;
-};
-
-/*
- * All SRP (and MAD) requests normally flow from the
- * client to the server. There is no way for the server to send
- * an asynchronous message back to the client. The Empty IU is used
- * to hang out a meaningless request to the server so that it can respond
- * asynchrouously with something like a SCSI AER
- */
-struct viosrp_empty_iu {
- struct mad_common common;
- __be64 buffer;
- __be32 port;
-};
-
-struct viosrp_error_log {
- struct mad_common common;
- __be64 buffer;
-};
-
-struct viosrp_adapter_info {
- struct mad_common common;
- __be64 buffer;
-};
-
-struct viosrp_fast_fail {
- struct mad_common common;
-};
-
-struct viosrp_capabilities {
- struct mad_common common;
- __be64 buffer;
-};
-
-struct mad_capability_common {
- __be32 cap_type;
- __be16 length;
- __be16 server_support;
-};
-
-struct mad_reserve_cap {
- struct mad_capability_common common;
- __be32 type;
-};
-
-struct mad_migration_cap {
- struct mad_capability_common common;
- __be32 ecl;
-};
-
-struct capabilities{
- __be32 flags;
- char name[SRP_MAX_LOC_LEN];
- char loc[SRP_MAX_LOC_LEN];
- struct mad_migration_cap migration;
- struct mad_reserve_cap reserve;
-};
-
-union mad_iu {
- struct viosrp_empty_iu empty_iu;
- struct viosrp_error_log error_log;
- struct viosrp_adapter_info adapter_info;
- struct viosrp_fast_fail fast_fail;
- struct viosrp_capabilities capabilities;
-};
-
-union viosrp_iu {
- union srp_iu srp;
- union mad_iu mad;
-};
-
-struct mad_adapter_info_data {
- char srp_version[8];
- char partition_name[96];
- __be32 partition_number;
-#define SRP_MAD_VERSION_1 1
- __be32 mad_version;
-#define SRP_MAD_OS_LINUX 2
-#define SRP_MAD_OS_AIX 3
- __be32 os_type;
- __be32 port_max_txu[8]; /* per-port maximum transfer */
-};
-
-#endif
diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig
deleted file mode 100644
index 7fec3b4c8..000000000
--- a/drivers/soc/brcmstb/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-menuconfig SOC_BRCMSTB
- bool "Broadcom STB SoC drivers"
- depends on ARM
- select SOC_BUS
- help
- Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
- This option alone enables only some support code, while the drivers
- can be enabled individually within this menu.
-
- If unsure, say N.
diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/brcmstb/Makefile
deleted file mode 100644
index 9120b2715..000000000
--- a/drivers/soc/brcmstb/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-y += common.o biuctrl.o
diff --git a/drivers/soc/brcmstb/biuctrl.c b/drivers/soc/brcmstb/biuctrl.c
deleted file mode 100644
index 9049c076f..000000000
--- a/drivers/soc/brcmstb/biuctrl.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Broadcom STB SoCs Bus Unit Interface controls
- *
- * Copyright (C) 2015, Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-#define pr_fmt(fmt) "brcmstb: " KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/of_address.h>
-#include <linux/syscore_ops.h>
-
-#define CPU_CREDIT_REG_OFFSET 0x184
-#define CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK 0x70000000
-
-static void __iomem *cpubiuctrl_base;
-static bool mcp_wr_pairing_en;
-
-static int __init mcp_write_pairing_set(void)
-{
- u32 creds = 0;
-
- if (!cpubiuctrl_base)
- return -1;
-
- creds = readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
- if (mcp_wr_pairing_en) {
- pr_info("MCP: Enabling write pairing\n");
- writel_relaxed(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
- cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
- } else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
- pr_info("MCP: Disabling write pairing\n");
- writel_relaxed(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
- cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
- } else {
- pr_info("MCP: Write pairing already disabled\n");
- }
-
- return 0;
-}
-
-static int __init setup_hifcpubiuctrl_regs(void)
-{
- struct device_node *np;
- int ret = 0;
-
- np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
- if (!np) {
- pr_err("missing BIU control node\n");
- return -ENODEV;
- }
-
- cpubiuctrl_base = of_iomap(np, 0);
- if (!cpubiuctrl_base) {
- pr_err("failed to remap BIU control base\n");
- ret = -ENOMEM;
- goto out;
- }
-
- mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
-out:
- of_node_put(np);
- return ret;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static u32 cpu_credit_reg_dump; /* for save/restore */
-
-static int brcmstb_cpu_credit_reg_suspend(void)
-{
- if (cpubiuctrl_base)
- cpu_credit_reg_dump =
- readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
- return 0;
-}
-
-static void brcmstb_cpu_credit_reg_resume(void)
-{
- if (cpubiuctrl_base)
- writel_relaxed(cpu_credit_reg_dump,
- cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
-}
-
-static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
- .suspend = brcmstb_cpu_credit_reg_suspend,
- .resume = brcmstb_cpu_credit_reg_resume,
-};
-#endif
-
-
-void __init brcmstb_biuctrl_init(void)
-{
- int ret;
-
- setup_hifcpubiuctrl_regs();
-
- ret = mcp_write_pairing_set();
- if (ret) {
- pr_err("MCP: Unable to disable write pairing!\n");
- return;
- }
-
-#ifdef CONFIG_PM_SLEEP
- register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
-#endif
-}
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
deleted file mode 100644
index 94e733555..000000000
--- a/drivers/soc/brcmstb/common.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright © 2014 NVIDIA Corporation
- * Copyright © 2015 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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 <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/slab.h>
-#include <linux/soc/brcmstb/brcmstb.h>
-#include <linux/sys_soc.h>
-
-#include <soc/brcmstb/common.h>
-
-static u32 family_id;
-static u32 product_id;
-
-static const struct of_device_id brcmstb_machine_match[] = {
- { .compatible = "brcm,brcmstb", },
- { }
-};
-
-bool soc_is_brcmstb(void)
-{
- struct device_node *root;
-
- root = of_find_node_by_path("/");
- if (!root)
- return false;
-
- return of_match_node(brcmstb_machine_match, root) != NULL;
-}
-
-static const struct of_device_id sun_top_ctrl_match[] = {
- { .compatible = "brcm,brcmstb-sun-top-ctrl", },
- { }
-};
-
-static int __init brcmstb_soc_device_init(void)
-{
- struct soc_device_attribute *soc_dev_attr;
- struct soc_device *soc_dev;
- struct device_node *sun_top_ctrl;
- void __iomem *sun_top_ctrl_base;
- int ret = 0;
-
- sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
- if (!sun_top_ctrl)
- return -ENODEV;
-
- sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
- if (!sun_top_ctrl_base)
- return -ENODEV;
-
- family_id = readl(sun_top_ctrl_base);
- product_id = readl(sun_top_ctrl_base + 0x4);
-
- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
- if (!soc_dev_attr) {
- ret = -ENOMEM;
- goto out;
- }
-
- soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
- family_id >> 28 ?
- family_id >> 16 : family_id >> 8);
- soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
- product_id >> 28 ?
- product_id >> 16 : product_id >> 8);
- soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
- ((product_id & 0xf0) >> 4) + 'A',
- product_id & 0xf);
-
- soc_dev = soc_device_register(soc_dev_attr);
- if (IS_ERR(soc_dev)) {
- kfree(soc_dev_attr->family);
- kfree(soc_dev_attr->soc_id);
- kfree(soc_dev_attr->revision);
- kfree(soc_dev_attr);
- ret = -ENODEV;
- goto out;
- }
-
- return 0;
-
-out:
- iounmap(sun_top_ctrl_base);
- return ret;
-}
-arch_initcall(brcmstb_soc_device_init);
diff --git a/drivers/spi/spi-octeon.c b/drivers/spi/spi-octeon.c
deleted file mode 100644
index 3b1700939..000000000
--- a/drivers/spi/spi-octeon.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2011, 2012 Cavium, Inc.
- */
-
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/spi/spi.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/of.h>
-
-#include <asm/octeon/octeon.h>
-#include <asm/octeon/cvmx-mpi-defs.h>
-
-#define OCTEON_SPI_CFG 0
-#define OCTEON_SPI_STS 0x08
-#define OCTEON_SPI_TX 0x10
-#define OCTEON_SPI_DAT0 0x80
-
-#define OCTEON_SPI_MAX_BYTES 9
-
-#define OCTEON_SPI_MAX_CLOCK_HZ 16000000
-
-struct octeon_spi {
- u64 register_base;
- u64 last_cfg;
- u64 cs_enax;
-};
-
-static void octeon_spi_wait_ready(struct octeon_spi *p)
-{
- union cvmx_mpi_sts mpi_sts;
- unsigned int loops = 0;
-
- do {
- if (loops++)
- __delay(500);
- mpi_sts.u64 = cvmx_read_csr(p->register_base + OCTEON_SPI_STS);
- } while (mpi_sts.s.busy);
-}
-
-static int octeon_spi_do_transfer(struct octeon_spi *p,
- struct spi_message *msg,
- struct spi_transfer *xfer,
- bool last_xfer)
-{
- struct spi_device *spi = msg->spi;
- union cvmx_mpi_cfg mpi_cfg;
- union cvmx_mpi_tx mpi_tx;
- unsigned int clkdiv;
- unsigned int speed_hz;
- int mode;
- bool cpha, cpol;
- const u8 *tx_buf;
- u8 *rx_buf;
- int len;
- int i;
-
- mode = spi->mode;
- cpha = mode & SPI_CPHA;
- cpol = mode & SPI_CPOL;
-
- speed_hz = xfer->speed_hz;
-
- clkdiv = octeon_get_io_clock_rate() / (2 * speed_hz);
-
- mpi_cfg.u64 = 0;
-
- mpi_cfg.s.clkdiv = clkdiv;
- mpi_cfg.s.cshi = (mode & SPI_CS_HIGH) ? 1 : 0;
- mpi_cfg.s.lsbfirst = (mode & SPI_LSB_FIRST) ? 1 : 0;
- mpi_cfg.s.wireor = (mode & SPI_3WIRE) ? 1 : 0;
- mpi_cfg.s.idlelo = cpha != cpol;
- mpi_cfg.s.cslate = cpha ? 1 : 0;
- mpi_cfg.s.enable = 1;
-
- if (spi->chip_select < 4)
- p->cs_enax |= 1ull << (12 + spi->chip_select);
- mpi_cfg.u64 |= p->cs_enax;
-
- if (mpi_cfg.u64 != p->last_cfg) {
- p->last_cfg = mpi_cfg.u64;
- cvmx_write_csr(p->register_base + OCTEON_SPI_CFG, mpi_cfg.u64);
- }
- tx_buf = xfer->tx_buf;
- rx_buf = xfer->rx_buf;
- len = xfer->len;
- while (len > OCTEON_SPI_MAX_BYTES) {
- for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {
- u8 d;
- if (tx_buf)
- d = *tx_buf++;
- else
- d = 0;
- cvmx_write_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i), d);
- }
- mpi_tx.u64 = 0;
- mpi_tx.s.csid = spi->chip_select;
- mpi_tx.s.leavecs = 1;
- mpi_tx.s.txnum = tx_buf ? OCTEON_SPI_MAX_BYTES : 0;
- mpi_tx.s.totnum = OCTEON_SPI_MAX_BYTES;
- cvmx_write_csr(p->register_base + OCTEON_SPI_TX, mpi_tx.u64);
-
- octeon_spi_wait_ready(p);
- if (rx_buf)
- for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {
- u64 v = cvmx_read_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i));
- *rx_buf++ = (u8)v;
- }
- len -= OCTEON_SPI_MAX_BYTES;
- }
-
- for (i = 0; i < len; i++) {
- u8 d;
- if (tx_buf)
- d = *tx_buf++;
- else
- d = 0;
- cvmx_write_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i), d);
- }
-
- mpi_tx.u64 = 0;
- mpi_tx.s.csid = spi->chip_select;
- if (last_xfer)
- mpi_tx.s.leavecs = xfer->cs_change;
- else
- mpi_tx.s.leavecs = !xfer->cs_change;
- mpi_tx.s.txnum = tx_buf ? len : 0;
- mpi_tx.s.totnum = len;
- cvmx_write_csr(p->register_base + OCTEON_SPI_TX, mpi_tx.u64);
-
- octeon_spi_wait_ready(p);
- if (rx_buf)
- for (i = 0; i < len; i++) {
- u64 v = cvmx_read_csr(p->register_base + OCTEON_SPI_DAT0 + (8 * i));
- *rx_buf++ = (u8)v;
- }
-
- if (xfer->delay_usecs)
- udelay(xfer->delay_usecs);
-
- return xfer->len;
-}
-
-static int octeon_spi_transfer_one_message(struct spi_master *master,
- struct spi_message *msg)
-{
- struct octeon_spi *p = spi_master_get_devdata(master);
- unsigned int total_len = 0;
- int status = 0;
- struct spi_transfer *xfer;
-
- list_for_each_entry(xfer, &msg->transfers, transfer_list) {
- bool last_xfer = list_is_last(&xfer->transfer_list,
- &msg->transfers);
- int r = octeon_spi_do_transfer(p, msg, xfer, last_xfer);
- if (r < 0) {
- status = r;
- goto err;
- }
- total_len += r;
- }
-err:
- msg->status = status;
- msg->actual_length = total_len;
- spi_finalize_current_message(master);
- return status;
-}
-
-static int octeon_spi_probe(struct platform_device *pdev)
-{
- struct resource *res_mem;
- void __iomem *reg_base;
- struct spi_master *master;
- struct octeon_spi *p;
- int err = -ENOENT;
-
- master = spi_alloc_master(&pdev->dev, sizeof(struct octeon_spi));
- if (!master)
- return -ENOMEM;
- p = spi_master_get_devdata(master);
- platform_set_drvdata(pdev, master);
-
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- reg_base = devm_ioremap_resource(&pdev->dev, res_mem);
- if (IS_ERR(reg_base)) {
- err = PTR_ERR(reg_base);
- goto fail;
- }
-
- p->register_base = (u64)reg_base;
-
- master->num_chipselect = 4;
- master->mode_bits = SPI_CPHA |
- SPI_CPOL |
- SPI_CS_HIGH |
- SPI_LSB_FIRST |
- SPI_3WIRE;
-
- master->transfer_one_message = octeon_spi_transfer_one_message;
- master->bits_per_word_mask = SPI_BPW_MASK(8);
- master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
-
- master->dev.of_node = pdev->dev.of_node;
- err = devm_spi_register_master(&pdev->dev, master);
- if (err) {
- dev_err(&pdev->dev, "register master failed: %d\n", err);
- goto fail;
- }
-
- dev_info(&pdev->dev, "OCTEON SPI bus driver\n");
-
- return 0;
-fail:
- spi_master_put(master);
- return err;
-}
-
-static int octeon_spi_remove(struct platform_device *pdev)
-{
- struct spi_master *master = platform_get_drvdata(pdev);
- struct octeon_spi *p = spi_master_get_devdata(master);
- u64 register_base = p->register_base;
-
- /* Clear the CSENA* and put everything in a known state. */
- cvmx_write_csr(register_base + OCTEON_SPI_CFG, 0);
-
- return 0;
-}
-
-static const struct of_device_id octeon_spi_match[] = {
- { .compatible = "cavium,octeon-3010-spi", },
- {},
-};
-MODULE_DEVICE_TABLE(of, octeon_spi_match);
-
-static struct platform_driver octeon_spi_driver = {
- .driver = {
- .name = "spi-octeon",
- .of_match_table = octeon_spi_match,
- },
- .probe = octeon_spi_probe,
- .remove = octeon_spi_remove,
-};
-
-module_platform_driver(octeon_spi_driver);
-
-MODULE_DESCRIPTION("Cavium, Inc. OCTEON SPI bus driver");
-MODULE_AUTHOR("David Daney");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/android/sw_sync.h b/drivers/staging/android/sw_sync.h
deleted file mode 100644
index e18667bfb..000000000
--- a/drivers/staging/android/sw_sync.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * include/linux/sw_sync.h
- *
- * Copyright (C) 2012 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef _LINUX_SW_SYNC_H
-#define _LINUX_SW_SYNC_H
-
-#include <linux/types.h>
-#include <linux/kconfig.h>
-#include "sync.h"
-#include "uapi/sw_sync.h"
-
-struct sw_sync_timeline {
- struct sync_timeline obj;
-
- u32 value;
-};
-
-struct sw_sync_pt {
- struct fence pt;
-
- u32 value;
-};
-
-#if IS_ENABLED(CONFIG_SW_SYNC)
-struct sw_sync_timeline *sw_sync_timeline_create(const char *name);
-void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc);
-
-struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value);
-#else
-static inline struct sw_sync_timeline *sw_sync_timeline_create(const char *name)
-{
- return NULL;
-}
-
-static inline void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc)
-{
-}
-
-static inline struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj,
- u32 value)
-{
- return NULL;
-}
-#endif /* IS_ENABLED(CONFIG_SW_SYNC) */
-
-#endif /* _LINUX_SW_SYNC_H */
diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
deleted file mode 100644
index 1d14c83c7..000000000
--- a/drivers/staging/android/sync.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * drivers/base/sync.c
- *
- * Copyright (C) 2012 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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 <linux/debugfs.h>
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/anon_inodes.h>
-
-#include "sync.h"
-
-#define CREATE_TRACE_POINTS
-#include "trace/sync.h"
-
-static const struct fence_ops android_fence_ops;
-
-struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
- int size, const char *name)
-{
- struct sync_timeline *obj;
-
- if (size < sizeof(struct sync_timeline))
- return NULL;
-
- obj = kzalloc(size, GFP_KERNEL);
- if (!obj)
- return NULL;
-
- kref_init(&obj->kref);
- obj->ops = ops;
- obj->context = fence_context_alloc(1);
- strlcpy(obj->name, name, sizeof(obj->name));
-
- INIT_LIST_HEAD(&obj->child_list_head);
- INIT_LIST_HEAD(&obj->active_list_head);
- spin_lock_init(&obj->child_list_lock);
-
- sync_timeline_debug_add(obj);
-
- return obj;
-}
-EXPORT_SYMBOL(sync_timeline_create);
-
-static void sync_timeline_free(struct kref *kref)
-{
- struct sync_timeline *obj =
- container_of(kref, struct sync_timeline, kref);
-
- sync_timeline_debug_remove(obj);
-
- kfree(obj);
-}
-
-static void sync_timeline_get(struct sync_timeline *obj)
-{
- kref_get(&obj->kref);
-}
-
-static void sync_timeline_put(struct sync_timeline *obj)
-{
- kref_put(&obj->kref, sync_timeline_free);
-}
-
-void sync_timeline_destroy(struct sync_timeline *obj)
-{
- obj->destroyed = true;
- /*
- * Ensure timeline is marked as destroyed before
- * changing timeline's fences status.
- */
- smp_wmb();
-
- sync_timeline_put(obj);
-}
-EXPORT_SYMBOL(sync_timeline_destroy);
-
-void sync_timeline_signal(struct sync_timeline *obj)
-{
- unsigned long flags;
- struct fence *fence, *next;
-
- trace_sync_timeline(obj);
-
- spin_lock_irqsave(&obj->child_list_lock, flags);
-
- list_for_each_entry_safe(fence, next, &obj->active_list_head,
- active_list) {
- if (fence_is_signaled_locked(fence))
- list_del_init(&fence->active_list);
- }
-
- spin_unlock_irqrestore(&obj->child_list_lock, flags);
-}
-EXPORT_SYMBOL(sync_timeline_signal);
-
-struct fence *sync_pt_create(struct sync_timeline *obj, int size)
-{
- unsigned long flags;
- struct fence *fence;
-
- if (size < sizeof(*fence))
- return NULL;
-
- fence = kzalloc(size, GFP_KERNEL);
- if (!fence)
- return NULL;
-
- spin_lock_irqsave(&obj->child_list_lock, flags);
- sync_timeline_get(obj);
- fence_init(fence, &android_fence_ops, &obj->child_list_lock,
- obj->context, ++obj->value);
- list_add_tail(&fence->child_list, &obj->child_list_head);
- INIT_LIST_HEAD(&fence->active_list);
- spin_unlock_irqrestore(&obj->child_list_lock, flags);
- return fence;
-}
-EXPORT_SYMBOL(sync_pt_create);
-
-static const char *android_fence_get_driver_name(struct fence *fence)
-{
- struct sync_timeline *parent = fence_parent(fence);
-
- return parent->ops->driver_name;
-}
-
-static const char *android_fence_get_timeline_name(struct fence *fence)
-{
- struct sync_timeline *parent = fence_parent(fence);
-
- return parent->name;
-}
-
-static void android_fence_release(struct fence *fence)
-{
- struct sync_timeline *parent = fence_parent(fence);
- unsigned long flags;
-
- spin_lock_irqsave(fence->lock, flags);
- list_del(&fence->child_list);
- if (WARN_ON_ONCE(!list_empty(&fence->active_list)))
- list_del(&fence->active_list);
- spin_unlock_irqrestore(fence->lock, flags);
-
- sync_timeline_put(parent);
- fence_free(fence);
-}
-
-static bool android_fence_signaled(struct fence *fence)
-{
- struct sync_timeline *parent = fence_parent(fence);
- int ret;
-
- ret = parent->ops->has_signaled(fence);
- if (ret < 0)
- fence->status = ret;
- return ret;
-}
-
-static bool android_fence_enable_signaling(struct fence *fence)
-{
- struct sync_timeline *parent = fence_parent(fence);
-
- if (android_fence_signaled(fence))
- return false;
-
- list_add_tail(&fence->active_list, &parent->active_list_head);
- return true;
-}
-
-static void android_fence_value_str(struct fence *fence,
- char *str, int size)
-{
- struct sync_timeline *parent = fence_parent(fence);
-
- if (!parent->ops->fence_value_str) {
- if (size)
- *str = 0;
- return;
- }
- parent->ops->fence_value_str(fence, str, size);
-}
-
-static void android_fence_timeline_value_str(struct fence *fence,
- char *str, int size)
-{
- struct sync_timeline *parent = fence_parent(fence);
-
- if (!parent->ops->timeline_value_str) {
- if (size)
- *str = 0;
- return;
- }
- parent->ops->timeline_value_str(parent, str, size);
-}
-
-static const struct fence_ops android_fence_ops = {
- .get_driver_name = android_fence_get_driver_name,
- .get_timeline_name = android_fence_get_timeline_name,
- .enable_signaling = android_fence_enable_signaling,
- .signaled = android_fence_signaled,
- .wait = fence_default_wait,
- .release = android_fence_release,
- .fence_value_str = android_fence_value_str,
- .timeline_value_str = android_fence_timeline_value_str,
-};
diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h
deleted file mode 100644
index b56885c14..000000000
--- a/drivers/staging/android/sync.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * include/linux/sync.h
- *
- * Copyright (C) 2012 Google, Inc.
- *
- * 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.
- *
- */
-
-#ifndef _LINUX_SYNC_H
-#define _LINUX_SYNC_H
-
-#include <linux/types.h>
-#include <linux/kref.h>
-#include <linux/ktime.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/fence.h>
-
-#include <linux/sync_file.h>
-#include <uapi/linux/sync_file.h>
-
-struct sync_timeline;
-
-/**
- * struct sync_timeline_ops - sync object implementation ops
- * @driver_name: name of the implementation
- * @has_signaled: returns:
- * 1 if pt has signaled
- * 0 if pt has not signaled
- * <0 on error
- * @timeline_value_str: fill str with the value of the sync_timeline's counter
- * @fence_value_str: fill str with the value of the fence
- */
-struct sync_timeline_ops {
- const char *driver_name;
-
- /* required */
- int (*has_signaled)(struct fence *fence);
-
- /* optional */
- void (*timeline_value_str)(struct sync_timeline *timeline, char *str,
- int size);
-
- /* optional */
- void (*fence_value_str)(struct fence *fence, char *str, int size);
-};
-
-/**
- * struct sync_timeline - sync object
- * @kref: reference count on fence.
- * @ops: ops that define the implementation of the sync_timeline
- * @name: name of the sync_timeline. Useful for debugging
- * @destroyed: set when sync_timeline is destroyed
- * @child_list_head: list of children sync_pts for this sync_timeline
- * @child_list_lock: lock protecting @child_list_head, destroyed, and
- * fence.status
- * @active_list_head: list of active (unsignaled/errored) sync_pts
- * @sync_timeline_list: membership in global sync_timeline_list
- */
-struct sync_timeline {
- struct kref kref;
- const struct sync_timeline_ops *ops;
- char name[32];
-
- /* protected by child_list_lock */
- bool destroyed;
- int context, value;
-
- struct list_head child_list_head;
- spinlock_t child_list_lock;
-
- struct list_head active_list_head;
-
-#ifdef CONFIG_DEBUG_FS
- struct list_head sync_timeline_list;
-#endif
-};
-
-static inline struct sync_timeline *fence_parent(struct fence *fence)
-{
- return container_of(fence->lock, struct sync_timeline,
- child_list_lock);
-}
-
-/*
- * API for sync_timeline implementers
- */
-
-/**
- * sync_timeline_create() - creates a sync object
- * @ops: specifies the implementation ops for the object
- * @size: size to allocate for this obj
- * @name: sync_timeline name
- *
- * Creates a new sync_timeline which will use the implementation specified by
- * @ops. @size bytes will be allocated allowing for implementation specific
- * data to be kept after the generic sync_timeline struct. Returns the
- * sync_timeline object or NULL in case of error.
- */
-struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
- int size, const char *name);
-
-/**
- * sync_timeline_destroy() - destroys a sync object
- * @obj: sync_timeline to destroy
- *
- * A sync implementation should call this when the @obj is going away
- * (i.e. module unload.) @obj won't actually be freed until all its children
- * fences are freed.
- */
-void sync_timeline_destroy(struct sync_timeline *obj);
-
-/**
- * sync_timeline_signal() - signal a status change on a sync_timeline
- * @obj: sync_timeline to signal
- *
- * A sync implementation should call this any time one of it's fences
- * has signaled or has an error condition.
- */
-void sync_timeline_signal(struct sync_timeline *obj);
-
-/**
- * sync_pt_create() - creates a sync pt
- * @parent: fence's parent sync_timeline
- * @size: size to allocate for this pt
- *
- * Creates a new fence as a child of @parent. @size bytes will be
- * allocated allowing for implementation specific data to be kept after
- * the generic sync_timeline struct. Returns the fence object or
- * NULL in case of error.
- */
-struct fence *sync_pt_create(struct sync_timeline *parent, int size);
-
-#ifdef CONFIG_DEBUG_FS
-
-void sync_timeline_debug_add(struct sync_timeline *obj);
-void sync_timeline_debug_remove(struct sync_timeline *obj);
-void sync_file_debug_add(struct sync_file *fence);
-void sync_file_debug_remove(struct sync_file *fence);
-void sync_dump(void);
-
-#else
-# define sync_timeline_debug_add(obj)
-# define sync_timeline_debug_remove(obj)
-# define sync_file_debug_add(fence)
-# define sync_file_debug_remove(fence)
-# define sync_dump()
-#endif
-
-#endif /* _LINUX_SYNC_H */
diff --git a/drivers/staging/android/uapi/sw_sync.h b/drivers/staging/android/uapi/sw_sync.h
deleted file mode 100644
index 9b5d48695..000000000
--- a/drivers/staging/android/uapi/sw_sync.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2012 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef _UAPI_LINUX_SW_SYNC_H
-#define _UAPI_LINUX_SW_SYNC_H
-
-#include <linux/types.h>
-
-struct sw_sync_create_fence_data {
- __u32 value;
- char name[32];
- __s32 fence; /* fd of new fence */
-};
-
-#define SW_SYNC_IOC_MAGIC 'W'
-
-#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
- struct sw_sync_create_fence_data)
-#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
-
-#endif /* _UAPI_LINUX_SW_SYNC_H */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
deleted file mode 100644
index f0c0d5838..000000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ /dev/null
@@ -1,187 +0,0 @@
-static int apci1564_timer_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct apci1564_private *devpriv = dev->private;
- unsigned int ctrl;
-
- devpriv->tsk_current = current;
-
- /* Stop the timer */
- ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
- ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
- ADDI_TCW_CTRL_ENA);
- outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
-
- if (data[1] == 1) {
- /* Enable timer int & disable all the other int sources */
- outl(ADDI_TCW_CTRL_IRQ_ENA,
- devpriv->timer + ADDI_TCW_CTRL_REG);
- outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
- outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
- outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
- if (devpriv->counters) {
- unsigned long iobase;
-
- iobase = devpriv->counters + ADDI_TCW_IRQ_REG;
- outl(0x0, iobase + APCI1564_COUNTER(0));
- outl(0x0, iobase + APCI1564_COUNTER(1));
- outl(0x0, iobase + APCI1564_COUNTER(2));
- }
- } else {
- /* disable Timer interrupt */
- outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG);
- }
-
- /* Loading Timebase */
- outl(data[2], devpriv->timer + ADDI_TCW_TIMEBASE_REG);
-
- /* Loading the Reload value */
- outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG);
-
- ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
- ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK |
- ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
- ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
- ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
- ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA;
- outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
-
- return insn->n;
-}
-
-static int apci1564_timer_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct apci1564_private *devpriv = dev->private;
- unsigned int ctrl;
-
- ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
- ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
- switch (data[1]) {
- case 0: /* Stop The Timer */
- ctrl &= ~ADDI_TCW_CTRL_ENA;
- break;
- case 1: /* Enable the Timer */
- ctrl |= ADDI_TCW_CTRL_ENA;
- break;
- }
- outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
-
- return insn->n;
-}
-
-static int apci1564_timer_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct apci1564_private *devpriv = dev->private;
-
- /* Stores the status of the Timer */
- data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) &
- ADDI_TCW_STATUS_OVERFLOW;
-
- /* Stores the Actual value of the Timer */
- data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG);
-
- return insn->n;
-}
-
-static int apci1564_counter_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct apci1564_private *devpriv = dev->private;
- unsigned int chan = CR_CHAN(insn->chanspec);
- unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
- unsigned int ctrl;
-
- devpriv->tsk_current = current;
-
- /* Stop The Timer */
- ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
- ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
- ADDI_TCW_CTRL_ENA);
- outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
- /* Set the reload value */
- outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
-
- /* Set the mode */
- ctrl &= ~(ADDI_TCW_CTRL_EXT_CLK_MASK | ADDI_TCW_CTRL_MODE_MASK |
- ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
- ADDI_TCW_CTRL_WARN_ENA);
- ctrl |= ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE(data[4]);
- outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
- /* Enable or Disable Interrupt */
- if (data[1])
- ctrl |= ADDI_TCW_CTRL_IRQ_ENA;
- else
- ctrl &= ~ADDI_TCW_CTRL_IRQ_ENA;
- outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
- /* Set the Up/Down selection */
- if (data[6])
- ctrl |= ADDI_TCW_CTRL_CNT_UP;
- else
- ctrl &= ~ADDI_TCW_CTRL_CNT_UP;
- outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
- return insn->n;
-}
-
-static int apci1564_counter_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct apci1564_private *devpriv = dev->private;
- unsigned int chan = CR_CHAN(insn->chanspec);
- unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
- unsigned int ctrl;
-
- ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
- ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
- switch (data[1]) {
- case 0: /* Stops the Counter subdevice */
- ctrl = 0;
- break;
- case 1: /* Start the Counter subdevice */
- ctrl |= ADDI_TCW_CTRL_ENA;
- break;
- case 2: /* Clears the Counter subdevice */
- ctrl |= ADDI_TCW_CTRL_GATE;
- break;
- }
- outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
- return insn->n;
-}
-
-static int apci1564_counter_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- struct apci1564_private *devpriv = dev->private;
- unsigned int chan = CR_CHAN(insn->chanspec);
- unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
- unsigned int status;
-
- /* Read the Counter Actual Value. */
- data[0] = inl(iobase + ADDI_TCW_VAL_REG);
-
- status = inl(iobase + ADDI_TCW_STATUS_REG);
- data[1] = (status & ADDI_TCW_STATUS_SOFT_TRIG) ? 1 : 0;
- data[2] = (status & ADDI_TCW_STATUS_HARDWARE_TRIG) ? 1 : 0;
- data[3] = (status & ADDI_TCW_STATUS_SOFT_CLR) ? 1 : 0;
- data[4] = (status & ADDI_TCW_STATUS_OVERFLOW) ? 1 : 0;
-
- return insn->n;
-}
diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h
deleted file mode 100644
index 6bd3d4d5b..000000000
--- a/drivers/staging/iio/accel/lis3l02dq.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * LISL02DQ.h -- support STMicroelectronics LISD02DQ
- * 3d 2g Linear Accelerometers via SPI
- *
- * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
- *
- * Loosely based upon tle62x0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef SPI_LIS3L02DQ_H_
-#define SPI_LIS3L02DQ_H_
-#define LIS3L02DQ_READ_REG(a) ((a) | 0x80)
-#define LIS3L02DQ_WRITE_REG(a) a
-
-/* Calibration parameters */
-#define LIS3L02DQ_REG_OFFSET_X_ADDR 0x16
-#define LIS3L02DQ_REG_OFFSET_Y_ADDR 0x17
-#define LIS3L02DQ_REG_OFFSET_Z_ADDR 0x18
-
-#define LIS3L02DQ_REG_GAIN_X_ADDR 0x19
-#define LIS3L02DQ_REG_GAIN_Y_ADDR 0x1A
-#define LIS3L02DQ_REG_GAIN_Z_ADDR 0x1B
-
-/* Control Register (1 of 2) */
-#define LIS3L02DQ_REG_CTRL_1_ADDR 0x20
-/* Power ctrl - either bit set corresponds to on*/
-#define LIS3L02DQ_REG_CTRL_1_PD_ON 0xC0
-
-/* Decimation Factor */
-#define LIS3L02DQ_DEC_MASK 0x30
-#define LIS3L02DQ_REG_CTRL_1_DF_128 0x00
-#define LIS3L02DQ_REG_CTRL_1_DF_64 0x10
-#define LIS3L02DQ_REG_CTRL_1_DF_32 0x20
-#define LIS3L02DQ_REG_CTRL_1_DF_8 (0x10 | 0x20)
-
-/* Self Test Enable */
-#define LIS3L02DQ_REG_CTRL_1_SELF_TEST_ON 0x08
-
-/* Axes enable ctrls */
-#define LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE 0x04
-#define LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE 0x02
-#define LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE 0x01
-
-/* Control Register (2 of 2) */
-#define LIS3L02DQ_REG_CTRL_2_ADDR 0x21
-
-/* Block Data Update only after MSB and LSB read */
-#define LIS3L02DQ_REG_CTRL_2_BLOCK_UPDATE 0x40
-
-/* Set to big endian output */
-#define LIS3L02DQ_REG_CTRL_2_BIG_ENDIAN 0x20
-
-/* Reboot memory content */
-#define LIS3L02DQ_REG_CTRL_2_REBOOT_MEMORY 0x10
-
-/* Interrupt Enable - applies data ready to the RDY pad */
-#define LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT 0x08
-
-/* Enable Data Ready Generation - relationship with previous unclear in docs */
-#define LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION 0x04
-
-/* SPI 3 wire mode */
-#define LIS3L02DQ_REG_CTRL_2_THREE_WIRE_SPI_MODE 0x02
-
-/* Data alignment, default is 12 bit right justified
- * - option for 16 bit left justified
- */
-#define LIS3L02DQ_REG_CTRL_2_DATA_ALIGNMENT_16_BIT_LEFT_JUSTIFIED 0x01
-
-/* Interrupt related stuff */
-#define LIS3L02DQ_REG_WAKE_UP_CFG_ADDR 0x23
-
-/* Switch from or combination of conditions to and */
-#define LIS3L02DQ_REG_WAKE_UP_CFG_BOOLEAN_AND 0x80
-
-/* Latch interrupt request,
- * if on ack must be given by reading the ack register
- */
-#define LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC 0x40
-
-/* Z Interrupt on High (above threshold) */
-#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH 0x20
-/* Z Interrupt on Low */
-#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW 0x10
-/* Y Interrupt on High */
-#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_HIGH 0x08
-/* Y Interrupt on Low */
-#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_LOW 0x04
-/* X Interrupt on High */
-#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_HIGH 0x02
-/* X Interrupt on Low */
-#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_LOW 0x01
-
-/* Register that gives description of what caused interrupt
- * - latched if set in CFG_ADDRES
- */
-#define LIS3L02DQ_REG_WAKE_UP_SRC_ADDR 0x24
-/* top bit ignored */
-/* Interrupt Active */
-#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_ACTIVATED 0x40
-/* Interupts that have been triggered */
-#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH 0x20
-#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW 0x10
-#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH 0x08
-#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW 0x04
-#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH 0x02
-#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW 0x01
-
-#define LIS3L02DQ_REG_WAKE_UP_ACK_ADDR 0x25
-
-/* Status register */
-#define LIS3L02DQ_REG_STATUS_ADDR 0x27
-/* XYZ axis data overrun - first is all overrun? */
-#define LIS3L02DQ_REG_STATUS_XYZ_OVERRUN 0x80
-#define LIS3L02DQ_REG_STATUS_Z_OVERRUN 0x40
-#define LIS3L02DQ_REG_STATUS_Y_OVERRUN 0x20
-#define LIS3L02DQ_REG_STATUS_X_OVERRUN 0x10
-/* XYZ new data available - first is all 3 available? */
-#define LIS3L02DQ_REG_STATUS_XYZ_NEW_DATA 0x08
-#define LIS3L02DQ_REG_STATUS_Z_NEW_DATA 0x04
-#define LIS3L02DQ_REG_STATUS_Y_NEW_DATA 0x02
-#define LIS3L02DQ_REG_STATUS_X_NEW_DATA 0x01
-
-/* The accelerometer readings - low and high bytes.
- * Form of high byte dependent on justification set in ctrl reg
- */
-#define LIS3L02DQ_REG_OUT_X_L_ADDR 0x28
-#define LIS3L02DQ_REG_OUT_X_H_ADDR 0x29
-#define LIS3L02DQ_REG_OUT_Y_L_ADDR 0x2A
-#define LIS3L02DQ_REG_OUT_Y_H_ADDR 0x2B
-#define LIS3L02DQ_REG_OUT_Z_L_ADDR 0x2C
-#define LIS3L02DQ_REG_OUT_Z_H_ADDR 0x2D
-
-/* Threshold values for all axes and both above and below thresholds
- * - i.e. there is only one value
- */
-#define LIS3L02DQ_REG_THS_L_ADDR 0x2E
-#define LIS3L02DQ_REG_THS_H_ADDR 0x2F
-
-#define LIS3L02DQ_DEFAULT_CTRL1 (LIS3L02DQ_REG_CTRL_1_PD_ON \
- | LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE \
- | LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE \
- | LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE \
- | LIS3L02DQ_REG_CTRL_1_DF_128)
-
-#define LIS3L02DQ_DEFAULT_CTRL2 0
-
-#define LIS3L02DQ_MAX_TX 12
-#define LIS3L02DQ_MAX_RX 12
-/**
- * struct lis3l02dq_state - device instance specific data
- * @us: actual spi_device
- * @trig: data ready trigger registered with iio
- * @buf_lock: mutex to protect tx and rx
- * @tx: transmit buffer
- * @rx: receive buffer
- **/
-struct lis3l02dq_state {
- struct spi_device *us;
- struct iio_trigger *trig;
- struct mutex buf_lock;
- int gpio;
- bool trigger_on;
-
- u8 tx[LIS3L02DQ_MAX_RX] ____cacheline_aligned;
- u8 rx[LIS3L02DQ_MAX_RX] ____cacheline_aligned;
-};
-
-int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev,
- u8 reg_address,
- u8 *val);
-
-int lis3l02dq_spi_write_reg_8(struct iio_dev *indio_dev,
- u8 reg_address,
- u8 val);
-
-int lis3l02dq_disable_all_events(struct iio_dev *indio_dev);
-
-#ifdef CONFIG_IIO_BUFFER
-/* At the moment triggers are only used for buffer
- * filling. This may change!
- */
-void lis3l02dq_remove_trigger(struct iio_dev *indio_dev);
-int lis3l02dq_probe_trigger(struct iio_dev *indio_dev);
-
-int lis3l02dq_configure_buffer(struct iio_dev *indio_dev);
-void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev);
-
-irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private);
-#define lis3l02dq_th lis3l02dq_data_rdy_trig_poll
-
-#else /* CONFIG_IIO_BUFFER */
-#define lis3l02dq_th lis3l02dq_nobuffer
-
-static inline void lis3l02dq_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
-{
- return 0;
-}
-
-static int lis3l02dq_configure_buffer(struct iio_dev *indio_dev)
-{
- return 0;
-}
-
-static inline void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev)
-{
-}
-#endif /* CONFIG_IIO_BUFFER */
-#endif /* SPI_LIS3L02DQ_H_ */
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
deleted file mode 100644
index 7a6fed3f2..000000000
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ /dev/null
@@ -1,814 +0,0 @@
-/*
- * lis3l02dq.c support STMicroelectronics LISD02DQ
- * 3d 2g Linear Accelerometers via SPI
- *
- * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Settings:
- * 16 bit left justified mode used.
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/events.h>
-#include <linux/iio/buffer.h>
-
-#include "lis3l02dq.h"
-
-/* At the moment the spi framework doesn't allow global setting of cs_change.
- * It's in the likely to be added comment at the top of spi.h.
- * This means that use cannot be made of spi_write etc.
- */
-/* direct copy of the irq_default_primary_handler */
-#ifndef CONFIG_IIO_BUFFER
-static irqreturn_t lis3l02dq_nobuffer(int irq, void *private)
-{
- return IRQ_WAKE_THREAD;
-}
-#endif
-
-/**
- * lis3l02dq_spi_read_reg_8() - read single byte from a single register
- * @indio_dev: iio_dev for this actual device
- * @reg_address: the address of the register to be read
- * @val: pass back the resulting value
- **/
-int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev,
- u8 reg_address, u8 *val)
-{
- struct lis3l02dq_state *st = iio_priv(indio_dev);
- int ret;
- struct spi_transfer xfer = {
- .tx_buf = st->tx,
- .rx_buf = st->rx,
- .bits_per_word = 8,
- .len = 2,
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = LIS3L02DQ_READ_REG(reg_address);
- st->tx[1] = 0;
-
- ret = spi_sync_transfer(st->us, &xfer, 1);
- *val = st->rx[1];
- mutex_unlock(&st->buf_lock);
-
- return ret;
-}
-
-/**
- * lis3l02dq_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio_dev for this device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-int lis3l02dq_spi_write_reg_8(struct iio_dev *indio_dev,
- u8 reg_address,
- u8 val)
-{
- int ret;
- struct lis3l02dq_state *st = iio_priv(indio_dev);
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = LIS3L02DQ_WRITE_REG(reg_address);
- st->tx[1] = val;
- ret = spi_write(st->us, st->tx, 2);
- mutex_unlock(&st->buf_lock);
-
- return ret;
-}
-
-/**
- * lisl302dq_spi_write_reg_s16() - write 2 bytes to a pair of registers
- * @indio_dev: iio_dev for this device
- * @lower_reg_address: the address of the lower of the two registers.
- * Second register is assumed to have address one greater.
- * @value: value to be written
- **/
-static int lis3l02dq_spi_write_reg_s16(struct iio_dev *indio_dev,
- u8 lower_reg_address,
- s16 value)
-{
- int ret;
- struct lis3l02dq_state *st = iio_priv(indio_dev);
- struct spi_transfer xfers[] = { {
- .tx_buf = st->tx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- }, {
- .tx_buf = st->tx + 2,
- .bits_per_word = 8,
- .len = 2,
- },
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = LIS3L02DQ_WRITE_REG(lower_reg_address);
- st->tx[1] = value & 0xFF;
- st->tx[2] = LIS3L02DQ_WRITE_REG(lower_reg_address + 1);
- st->tx[3] = (value >> 8) & 0xFF;
-
- ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
- mutex_unlock(&st->buf_lock);
-
- return ret;
-}
-
-static int lis3l02dq_read_reg_s16(struct iio_dev *indio_dev,
- u8 lower_reg_address,
- int *val)
-{
- struct lis3l02dq_state *st = iio_priv(indio_dev);
- int ret;
- s16 tempval;
- struct spi_transfer xfers[] = { {
- .tx_buf = st->tx,
- .rx_buf = st->rx,
- .bits_per_word = 8,
- .len = 2,
- .cs_change = 1,
- }, {
- .tx_buf = st->tx + 2,
- .rx_buf = st->rx + 2,
- .bits_per_word = 8,
- .len = 2,
- },
- };
-
- mutex_lock(&st->buf_lock);
- st->tx[0] = LIS3L02DQ_READ_REG(lower_reg_address);
- st->tx[1] = 0;
- st->tx[2] = LIS3L02DQ_READ_REG(lower_reg_address + 1);
- st->tx[3] = 0;
-
- ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
- if (ret) {
- dev_err(&st->us->dev, "problem when reading 16 bit register");
- goto error_ret;
- }
- tempval = (s16)(st->rx[1]) | ((s16)(st->rx[3]) << 8);
-
- *val = tempval;
-error_ret:
- mutex_unlock(&st->buf_lock);
- return ret;
-}
-
-enum lis3l02dq_rm_ind {
- LIS3L02DQ_ACCEL,
- LIS3L02DQ_GAIN,
- LIS3L02DQ_BIAS,
-};
-
-static u8 lis3l02dq_axis_map[3][3] = {
- [LIS3L02DQ_ACCEL] = { LIS3L02DQ_REG_OUT_X_L_ADDR,
- LIS3L02DQ_REG_OUT_Y_L_ADDR,
- LIS3L02DQ_REG_OUT_Z_L_ADDR },
- [LIS3L02DQ_GAIN] = { LIS3L02DQ_REG_GAIN_X_ADDR,
- LIS3L02DQ_REG_GAIN_Y_ADDR,
- LIS3L02DQ_REG_GAIN_Z_ADDR },
- [LIS3L02DQ_BIAS] = { LIS3L02DQ_REG_OFFSET_X_ADDR,
- LIS3L02DQ_REG_OFFSET_Y_ADDR,
- LIS3L02DQ_REG_OFFSET_Z_ADDR }
-};
-
-static int lis3l02dq_read_thresh(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- enum iio_event_info info,
- int *val, int *val2)
-{
- int ret;
-
- ret = lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val);
- if (ret)
- return ret;
- return IIO_VAL_INT;
-}
-
-static int lis3l02dq_write_thresh(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- enum iio_event_info info,
- int val, int val2)
-{
- u16 value = val;
-
- return lis3l02dq_spi_write_reg_s16(indio_dev,
- LIS3L02DQ_REG_THS_L_ADDR,
- value);
-}
-
-static int lis3l02dq_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val,
- int val2,
- long mask)
-{
- int ret = -EINVAL, reg;
- u8 uval;
- s8 sval;
-
- switch (mask) {
- case IIO_CHAN_INFO_CALIBBIAS:
- if (val > 255 || val < -256)
- return -EINVAL;
- sval = val;
- reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address];
- ret = lis3l02dq_spi_write_reg_8(indio_dev, reg, sval);
- break;
- case IIO_CHAN_INFO_CALIBSCALE:
- if (val & ~0xFF)
- return -EINVAL;
- uval = val;
- reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN][chan->address];
- ret = lis3l02dq_spi_write_reg_8(indio_dev, reg, uval);
- break;
- }
- return ret;
-}
-
-static int lis3l02dq_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val,
- int *val2,
- long mask)
-{
- u8 utemp;
- s8 stemp;
- ssize_t ret = 0;
- u8 reg;
-
- switch (mask) {
- case IIO_CHAN_INFO_RAW:
- /* Take the iio_dev status lock */
- mutex_lock(&indio_dev->mlock);
- if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
- ret = -EBUSY;
- } else {
- reg = lis3l02dq_axis_map
- [LIS3L02DQ_ACCEL][chan->address];
- ret = lis3l02dq_read_reg_s16(indio_dev, reg, val);
- }
- mutex_unlock(&indio_dev->mlock);
- if (ret < 0)
- goto error_ret;
- return IIO_VAL_INT;
- case IIO_CHAN_INFO_SCALE:
- *val = 0;
- *val2 = 9580;
- return IIO_VAL_INT_PLUS_MICRO;
- case IIO_CHAN_INFO_CALIBSCALE:
- reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN][chan->address];
- ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, &utemp);
- if (ret)
- goto error_ret;
- /* to match with what previous code does */
- *val = utemp;
- return IIO_VAL_INT;
-
- case IIO_CHAN_INFO_CALIBBIAS:
- reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address];
- ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, (u8 *)&stemp);
- /* to match with what previous code does */
- *val = stemp;
- return IIO_VAL_INT;
- }
-error_ret:
- return ret;
-}
-
-static ssize_t lis3l02dq_read_frequency(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- int ret, len = 0;
- s8 t;
-
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- (u8 *)&t);
- if (ret)
- return ret;
- t &= LIS3L02DQ_DEC_MASK;
- switch (t) {
- case LIS3L02DQ_REG_CTRL_1_DF_128:
- len = sprintf(buf, "280\n");
- break;
- case LIS3L02DQ_REG_CTRL_1_DF_64:
- len = sprintf(buf, "560\n");
- break;
- case LIS3L02DQ_REG_CTRL_1_DF_32:
- len = sprintf(buf, "1120\n");
- break;
- case LIS3L02DQ_REG_CTRL_1_DF_8:
- len = sprintf(buf, "4480\n");
- break;
- }
- return len;
-}
-
-static ssize_t lis3l02dq_write_frequency(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- unsigned long val;
- int ret;
- u8 t;
-
- ret = kstrtoul(buf, 10, &val);
- if (ret)
- return ret;
-
- mutex_lock(&indio_dev->mlock);
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- &t);
- if (ret)
- goto error_ret_mutex;
- /* Wipe the bits clean */
- t &= ~LIS3L02DQ_DEC_MASK;
- switch (val) {
- case 280:
- t |= LIS3L02DQ_REG_CTRL_1_DF_128;
- break;
- case 560:
- t |= LIS3L02DQ_REG_CTRL_1_DF_64;
- break;
- case 1120:
- t |= LIS3L02DQ_REG_CTRL_1_DF_32;
- break;
- case 4480:
- t |= LIS3L02DQ_REG_CTRL_1_DF_8;
- break;
- default:
- ret = -EINVAL;
- goto error_ret_mutex;
- }
-
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- t);
-
-error_ret_mutex:
- mutex_unlock(&indio_dev->mlock);
-
- return ret ? ret : len;
-}
-
-static int lis3l02dq_initial_setup(struct iio_dev *indio_dev)
-{
- struct lis3l02dq_state *st = iio_priv(indio_dev);
- int ret;
- u8 val, valtest;
-
- st->us->mode = SPI_MODE_3;
-
- spi_setup(st->us);
-
- val = LIS3L02DQ_DEFAULT_CTRL1;
- /* Write suitable defaults to ctrl1 */
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- val);
- if (ret) {
- dev_err(&st->us->dev, "problem with setup control register 1");
- goto err_ret;
- }
- /* Repeat as sometimes doesn't work first time? */
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- val);
- if (ret) {
- dev_err(&st->us->dev, "problem with setup control register 1");
- goto err_ret;
- }
-
- /*
- * Read back to check this has worked acts as loose test of correct
- * chip
- */
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- &valtest);
- if (ret || (valtest != val)) {
- dev_err(&indio_dev->dev,
- "device not playing ball %d %d\n", valtest, val);
- ret = -EINVAL;
- goto err_ret;
- }
-
- val = LIS3L02DQ_DEFAULT_CTRL2;
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- val);
- if (ret) {
- dev_err(&st->us->dev, "problem with setup control register 2");
- goto err_ret;
- }
-
- val = LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC;
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- val);
- if (ret)
- dev_err(&st->us->dev, "problem with interrupt cfg register");
-err_ret:
-
- return ret;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
- lis3l02dq_read_frequency,
- lis3l02dq_write_frequency);
-
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("280 560 1120 4480");
-
-static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
-{
- struct iio_dev *indio_dev = private;
- u8 t;
-
- s64 timestamp = iio_get_time_ns();
-
- lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_WAKE_UP_SRC_ADDR,
- &t);
-
- if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH)
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL,
- 0,
- IIO_MOD_Z,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_RISING),
- timestamp);
-
- if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW)
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL,
- 0,
- IIO_MOD_Z,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_FALLING),
- timestamp);
-
- if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH)
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL,
- 0,
- IIO_MOD_Y,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_RISING),
- timestamp);
-
- if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW)
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL,
- 0,
- IIO_MOD_Y,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_FALLING),
- timestamp);
-
- if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH)
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL,
- 0,
- IIO_MOD_X,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_RISING),
- timestamp);
-
- if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW)
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL,
- 0,
- IIO_MOD_X,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_FALLING),
- timestamp);
-
- /* Ack and allow for new interrupts */
- lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_WAKE_UP_ACK_ADDR,
- &t);
-
- return IRQ_HANDLED;
-}
-
-static const struct iio_event_spec lis3l02dq_event[] = {
- {
- .type = IIO_EV_TYPE_THRESH,
- .dir = IIO_EV_DIR_RISING,
- .mask_separate = BIT(IIO_EV_INFO_ENABLE),
- .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
- }, {
- .type = IIO_EV_TYPE_THRESH,
- .dir = IIO_EV_DIR_FALLING,
- .mask_separate = BIT(IIO_EV_INFO_ENABLE),
- .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
- }
-};
-
-#define LIS3L02DQ_CHAN(index, mod) \
- { \
- .type = IIO_ACCEL, \
- .modified = 1, \
- .channel2 = mod, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
- BIT(IIO_CHAN_INFO_CALIBSCALE) | \
- BIT(IIO_CHAN_INFO_CALIBBIAS), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
- .address = index, \
- .scan_index = index, \
- .scan_type = { \
- .sign = 's', \
- .realbits = 12, \
- .storagebits = 16, \
- }, \
- .event_spec = lis3l02dq_event, \
- .num_event_specs = ARRAY_SIZE(lis3l02dq_event), \
- }
-
-static const struct iio_chan_spec lis3l02dq_channels[] = {
- LIS3L02DQ_CHAN(0, IIO_MOD_X),
- LIS3L02DQ_CHAN(1, IIO_MOD_Y),
- LIS3L02DQ_CHAN(2, IIO_MOD_Z),
- IIO_CHAN_SOFT_TIMESTAMP(3)
-};
-
-static int lis3l02dq_read_event_config(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir)
-{
- u8 val;
- int ret;
- u8 mask = 1 << (chan->channel2 * 2 + (dir == IIO_EV_DIR_RISING));
-
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- &val);
- if (ret < 0)
- return ret;
-
- return !!(val & mask);
-}
-
-int lis3l02dq_disable_all_events(struct iio_dev *indio_dev)
-{
- int ret;
- u8 control, val;
-
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- &control);
-
- control &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT;
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- control);
- if (ret)
- goto error_ret;
- /* Also for consistency clear the mask */
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- &val);
- if (ret)
- goto error_ret;
- val &= ~0x3f;
-
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- val);
- if (ret)
- goto error_ret;
-
- ret = control;
-error_ret:
- return ret;
-}
-
-static int lis3l02dq_write_event_config(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- int state)
-{
- int ret = 0;
- u8 val, control;
- u8 currentlyset;
- bool changed = false;
- u8 mask = 1 << (chan->channel2 * 2 + (dir == IIO_EV_DIR_RISING));
-
- mutex_lock(&indio_dev->mlock);
- /* read current control */
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- &control);
- if (ret)
- goto error_ret;
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- &val);
- if (ret < 0)
- goto error_ret;
- currentlyset = val & mask;
-
- if (!currentlyset && state) {
- changed = true;
- val |= mask;
- } else if (currentlyset && !state) {
- changed = true;
- val &= ~mask;
- }
-
- if (changed) {
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
- val);
- if (ret)
- goto error_ret;
- control = val & 0x3f ?
- (control | LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT) :
- (control & ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT);
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- control);
- if (ret)
- goto error_ret;
- }
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
- return ret;
-}
-
-static struct attribute *lis3l02dq_attributes[] = {
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group lis3l02dq_attribute_group = {
- .attrs = lis3l02dq_attributes,
-};
-
-static const struct iio_info lis3l02dq_info = {
- .read_raw = &lis3l02dq_read_raw,
- .write_raw = &lis3l02dq_write_raw,
- .read_event_value = &lis3l02dq_read_thresh,
- .write_event_value = &lis3l02dq_write_thresh,
- .write_event_config = &lis3l02dq_write_event_config,
- .read_event_config = &lis3l02dq_read_event_config,
- .driver_module = THIS_MODULE,
- .attrs = &lis3l02dq_attribute_group,
-};
-
-static int lis3l02dq_probe(struct spi_device *spi)
-{
- int ret;
- struct lis3l02dq_state *st;
- struct iio_dev *indio_dev;
-
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
- if (!indio_dev)
- return -ENOMEM;
- st = iio_priv(indio_dev);
- /* this is only used for removal purposes */
- spi_set_drvdata(spi, indio_dev);
-
- st->us = spi;
- st->gpio = of_get_gpio(spi->dev.of_node, 0);
- mutex_init(&st->buf_lock);
- indio_dev->name = spi->dev.driver->name;
- indio_dev->dev.parent = &spi->dev;
- indio_dev->info = &lis3l02dq_info;
- indio_dev->channels = lis3l02dq_channels;
- indio_dev->num_channels = ARRAY_SIZE(lis3l02dq_channels);
-
- indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = lis3l02dq_configure_buffer(indio_dev);
- if (ret)
- return ret;
-
- if (spi->irq) {
- ret = request_threaded_irq(st->us->irq,
- &lis3l02dq_th,
- &lis3l02dq_event_handler,
- IRQF_TRIGGER_RISING,
- "lis3l02dq",
- indio_dev);
- if (ret)
- goto error_unreg_buffer_funcs;
-
- ret = lis3l02dq_probe_trigger(indio_dev);
- if (ret)
- goto error_free_interrupt;
- }
-
- /* Get the device into a sane initial state */
- ret = lis3l02dq_initial_setup(indio_dev);
- if (ret)
- goto error_remove_trigger;
-
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_remove_trigger;
-
- return 0;
-
-error_remove_trigger:
- if (spi->irq)
- lis3l02dq_remove_trigger(indio_dev);
-error_free_interrupt:
- if (spi->irq)
- free_irq(st->us->irq, indio_dev);
-error_unreg_buffer_funcs:
- lis3l02dq_unconfigure_buffer(indio_dev);
- return ret;
-}
-
-/* Power down the device */
-static int lis3l02dq_stop_device(struct iio_dev *indio_dev)
-{
- int ret;
- struct lis3l02dq_state *st = iio_priv(indio_dev);
- u8 val = 0;
-
- mutex_lock(&indio_dev->mlock);
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- val);
- if (ret) {
- dev_err(&st->us->dev, "problem with turning device off: ctrl1");
- goto err_ret;
- }
-
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- val);
- if (ret)
- dev_err(&st->us->dev, "problem with turning device off: ctrl2");
-err_ret:
- mutex_unlock(&indio_dev->mlock);
- return ret;
-}
-
-/* fixme, confirm ordering in this function */
-static int lis3l02dq_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct lis3l02dq_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- lis3l02dq_disable_all_events(indio_dev);
- lis3l02dq_stop_device(indio_dev);
-
- if (spi->irq)
- free_irq(st->us->irq, indio_dev);
-
- lis3l02dq_remove_trigger(indio_dev);
- lis3l02dq_unconfigure_buffer(indio_dev);
-
- return 0;
-}
-
-static struct spi_driver lis3l02dq_driver = {
- .driver = {
- .name = "lis3l02dq",
- },
- .probe = lis3l02dq_probe,
- .remove = lis3l02dq_remove,
-};
-module_spi_driver(lis3l02dq_driver);
-
-MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
-MODULE_DESCRIPTION("ST LIS3L02DQ Accelerometer SPI driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:lis3l02dq");
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
deleted file mode 100644
index 50c162e0c..000000000
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ /dev/null
@@ -1,428 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/kfifo_buf.h>
-#include <linux/iio/trigger.h>
-#include <linux/iio/trigger_consumer.h>
-#include "lis3l02dq.h"
-
-/**
- * combine_8_to_16() utility function to munge two u8s into u16
- **/
-static inline u16 combine_8_to_16(u8 lower, u8 upper)
-{
- u16 _lower = lower;
- u16 _upper = upper;
-
- return _lower | (_upper << 8);
-}
-
-/**
- * lis3l02dq_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private)
-{
- struct iio_dev *indio_dev = private;
- struct lis3l02dq_state *st = iio_priv(indio_dev);
-
- if (st->trigger_on) {
- iio_trigger_poll(st->trig);
- return IRQ_HANDLED;
- }
-
- return IRQ_WAKE_THREAD;
-}
-
-static const u8 read_all_tx_array[] = {
- LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_X_L_ADDR), 0,
- LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_X_H_ADDR), 0,
- LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_Y_L_ADDR), 0,
- LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_Y_H_ADDR), 0,
- LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_Z_L_ADDR), 0,
- LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_Z_H_ADDR), 0,
-};
-
-/**
- * lis3l02dq_read_all() Reads all channels currently selected
- * @indio_dev: IIO device state
- * @rx_array: (dma capable) receive array, must be at least
- * 4*number of channels
- **/
-static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array)
-{
- struct lis3l02dq_state *st = iio_priv(indio_dev);
- struct spi_transfer *xfers;
- struct spi_message msg;
- int ret, i, j = 0;
-
- xfers = kcalloc(bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength) * 2,
- sizeof(*xfers), GFP_KERNEL);
- if (!xfers)
- return -ENOMEM;
-
- mutex_lock(&st->buf_lock);
-
- for (i = 0; i < ARRAY_SIZE(read_all_tx_array) / 4; i++)
- if (test_bit(i, indio_dev->active_scan_mask)) {
- /* lower byte */
- xfers[j].tx_buf = st->tx + (2 * j);
- st->tx[2 * j] = read_all_tx_array[i * 4];
- st->tx[2 * j + 1] = 0;
- if (rx_array)
- xfers[j].rx_buf = rx_array + (j * 2);
- xfers[j].bits_per_word = 8;
- xfers[j].len = 2;
- xfers[j].cs_change = 1;
- j++;
-
- /* upper byte */
- xfers[j].tx_buf = st->tx + (2 * j);
- st->tx[2 * j] = read_all_tx_array[i * 4 + 2];
- st->tx[2 * j + 1] = 0;
- if (rx_array)
- xfers[j].rx_buf = rx_array + (j * 2);
- xfers[j].bits_per_word = 8;
- xfers[j].len = 2;
- xfers[j].cs_change = 1;
- j++;
- }
-
- /* After these are transmitted, the rx_buff should have
- * values in alternate bytes
- */
- spi_message_init(&msg);
- for (j = 0; j < bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength) * 2; j++)
- spi_message_add_tail(&xfers[j], &msg);
-
- ret = spi_sync(st->us, &msg);
- mutex_unlock(&st->buf_lock);
- kfree(xfers);
-
- return ret;
-}
-
-static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev,
- u8 *buf)
-{
- int ret, i;
- u8 *rx_array;
- s16 *data = (s16 *)buf;
- int scan_count = bitmap_weight(indio_dev->active_scan_mask,
- indio_dev->masklength);
-
- rx_array = kcalloc(4, scan_count, GFP_KERNEL);
- if (!rx_array)
- return -ENOMEM;
- ret = lis3l02dq_read_all(indio_dev, rx_array);
- if (ret < 0) {
- kfree(rx_array);
- return ret;
- }
- for (i = 0; i < scan_count; i++)
- data[i] = combine_8_to_16(rx_array[i * 4 + 1],
- rx_array[i * 4 + 3]);
- kfree(rx_array);
-
- return i * sizeof(data[0]);
-}
-
-static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
-{
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
- int len = 0;
- char *data;
-
- data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
- if (!data)
- goto done;
-
- if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
- len = lis3l02dq_get_buffer_element(indio_dev, data);
-
- iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp);
-
- kfree(data);
-done:
- iio_trigger_notify_done(indio_dev->trig);
- return IRQ_HANDLED;
-}
-
-/* Caller responsible for locking as necessary. */
-static int
-__lis3l02dq_write_data_ready_config(struct iio_dev *indio_dev, bool state)
-{
- int ret;
- u8 valold;
- bool currentlyset;
- struct lis3l02dq_state *st = iio_priv(indio_dev);
-
- /* Get the current event mask register */
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- &valold);
- if (ret)
- goto error_ret;
- /* Find out if data ready is already on */
- currentlyset
- = valold & LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION;
-
- /* Disable requested */
- if (!state && currentlyset) {
- /* Disable the data ready signal */
- valold &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION;
-
- /* The double write is to overcome a hardware bug? */
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- valold);
- if (ret)
- goto error_ret;
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- valold);
- if (ret)
- goto error_ret;
- st->trigger_on = false;
- /* Enable requested */
- } else if (state && !currentlyset) {
- /* If not set, enable requested
- * first disable all events
- */
- ret = lis3l02dq_disable_all_events(indio_dev);
- if (ret < 0)
- goto error_ret;
-
- valold = ret |
- LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION;
-
- st->trigger_on = true;
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_2_ADDR,
- valold);
- if (ret)
- goto error_ret;
- }
-
- return 0;
-error_ret:
- return ret;
-}
-
-/**
- * lis3l02dq_data_rdy_trigger_set_state() set datardy interrupt state
- *
- * If disabling the interrupt also does a final read to ensure it is clear.
- * This is only important in some cases where the scan enable elements are
- * switched before the buffer is reenabled.
- **/
-static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
- bool state)
-{
- struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
- int ret = 0;
- u8 t;
-
- __lis3l02dq_write_data_ready_config(indio_dev, state);
- if (!state) {
- /*
- * A possible quirk with the handler is currently worked around
- * by ensuring outstanding read events are cleared.
- */
- ret = lis3l02dq_read_all(indio_dev, NULL);
- }
- lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_WAKE_UP_SRC_ADDR,
- &t);
- return ret;
-}
-
-/**
- * lis3l02dq_trig_try_reen() try reenabling irq for data rdy trigger
- * @trig: the datardy trigger
- */
-static int lis3l02dq_trig_try_reen(struct iio_trigger *trig)
-{
- struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
- struct lis3l02dq_state *st = iio_priv(indio_dev);
- int i;
-
- /* If gpio still high (or high again)
- * In theory possible we will need to do this several times
- */
- for (i = 0; i < 5; i++)
- if (gpio_get_value(st->gpio))
- lis3l02dq_read_all(indio_dev, NULL);
- else
- break;
- if (i == 5)
- pr_info("Failed to clear the interrupt for lis3l02dq\n");
-
- /* irq reenabled so success! */
- return 0;
-}
-
-static const struct iio_trigger_ops lis3l02dq_trigger_ops = {
- .owner = THIS_MODULE,
- .set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state,
- .try_reenable = &lis3l02dq_trig_try_reen,
-};
-
-int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
-{
- int ret;
- struct lis3l02dq_state *st = iio_priv(indio_dev);
-
- st->trig = iio_trigger_alloc("lis3l02dq-dev%d", indio_dev->id);
- if (!st->trig) {
- ret = -ENOMEM;
- goto error_ret;
- }
-
- st->trig->dev.parent = &st->us->dev;
- st->trig->ops = &lis3l02dq_trigger_ops;
- iio_trigger_set_drvdata(st->trig, indio_dev);
- ret = iio_trigger_register(st->trig);
- if (ret)
- goto error_free_trig;
-
- return 0;
-
-error_free_trig:
- iio_trigger_free(st->trig);
-error_ret:
- return ret;
-}
-
-void lis3l02dq_remove_trigger(struct iio_dev *indio_dev)
-{
- struct lis3l02dq_state *st = iio_priv(indio_dev);
-
- iio_trigger_unregister(st->trig);
- iio_trigger_free(st->trig);
-}
-
-void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev)
-{
- iio_dealloc_pollfunc(indio_dev->pollfunc);
- iio_kfifo_free(indio_dev->buffer);
-}
-
-static int lis3l02dq_buffer_postenable(struct iio_dev *indio_dev)
-{
- /* Disable unwanted channels otherwise the interrupt will not clear */
- u8 t;
- int ret;
- bool oneenabled = false;
-
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- &t);
- if (ret)
- goto error_ret;
-
- if (test_bit(0, indio_dev->active_scan_mask)) {
- t |= LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE;
- oneenabled = true;
- } else {
- t &= ~LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE;
- }
- if (test_bit(1, indio_dev->active_scan_mask)) {
- t |= LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE;
- oneenabled = true;
- } else {
- t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE;
- }
- if (test_bit(2, indio_dev->active_scan_mask)) {
- t |= LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
- oneenabled = true;
- } else {
- t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
- }
- if (!oneenabled) /* what happens in this case is unknown */
- return -EINVAL;
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- t);
- if (ret)
- goto error_ret;
-
- return iio_triggered_buffer_postenable(indio_dev);
-error_ret:
- return ret;
-}
-
-/* Turn all channels on again */
-static int lis3l02dq_buffer_predisable(struct iio_dev *indio_dev)
-{
- u8 t;
- int ret;
-
- ret = iio_triggered_buffer_predisable(indio_dev);
- if (ret)
- goto error_ret;
-
- ret = lis3l02dq_spi_read_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- &t);
- if (ret)
- goto error_ret;
- t |= LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE |
- LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE |
- LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
-
- ret = lis3l02dq_spi_write_reg_8(indio_dev,
- LIS3L02DQ_REG_CTRL_1_ADDR,
- t);
-
-error_ret:
- return ret;
-}
-
-static const struct iio_buffer_setup_ops lis3l02dq_buffer_setup_ops = {
- .postenable = &lis3l02dq_buffer_postenable,
- .predisable = &lis3l02dq_buffer_predisable,
-};
-
-int lis3l02dq_configure_buffer(struct iio_dev *indio_dev)
-{
- int ret;
- struct iio_buffer *buffer;
-
- buffer = iio_kfifo_allocate();
- if (!buffer)
- return -ENOMEM;
-
- iio_device_attach_buffer(indio_dev, buffer);
-
- buffer->scan_timestamp = true;
- indio_dev->setup_ops = &lis3l02dq_buffer_setup_ops;
-
- /* Functions are NULL as we set handler below */
- indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
- &lis3l02dq_trigger_handler,
- 0,
- indio_dev,
- "lis3l02dq_consumer%d",
- indio_dev->id);
-
- if (!indio_dev->pollfunc) {
- ret = -ENOMEM;
- goto error_iio_sw_rb_free;
- }
-
- indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
- return 0;
-
-error_iio_sw_rb_free:
- iio_kfifo_free(indio_dev->buffer);
- return ret;
-}
diff --git a/drivers/staging/lustre/lustre/llite/llite_rmtacl.c b/drivers/staging/lustre/lustre/llite/llite_rmtacl.c
deleted file mode 100644
index 8509b07cb..000000000
--- a/drivers/staging/lustre/lustre/llite/llite_rmtacl.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/llite/llite_rmtacl.c
- *
- * Lustre Remote User Access Control List.
- *
- * Author: Fan Yong <fanyong@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#ifdef CONFIG_FS_POSIX_ACL
-
-#include "../include/lustre_lite.h"
-#include "../include/lustre_eacl.h"
-#include "llite_internal.h"
-
-static inline __u32 rce_hashfunc(uid_t id)
-{
- return id & (RCE_HASHES - 1);
-}
-
-static inline __u32 ee_hashfunc(uid_t id)
-{
- return id & (EE_HASHES - 1);
-}
-
-u64 rce_ops2valid(int ops)
-{
- switch (ops) {
- case RMT_LSETFACL:
- return OBD_MD_FLRMTLSETFACL;
- case RMT_LGETFACL:
- return OBD_MD_FLRMTLGETFACL;
- case RMT_RSETFACL:
- return OBD_MD_FLRMTRSETFACL;
- case RMT_RGETFACL:
- return OBD_MD_FLRMTRGETFACL;
- default:
- return 0;
- }
-}
-
-static struct rmtacl_ctl_entry *rce_alloc(pid_t key, int ops)
-{
- struct rmtacl_ctl_entry *rce;
-
- rce = kzalloc(sizeof(*rce), GFP_NOFS);
- if (!rce)
- return NULL;
-
- INIT_LIST_HEAD(&rce->rce_list);
- rce->rce_key = key;
- rce->rce_ops = ops;
-
- return rce;
-}
-
-static void rce_free(struct rmtacl_ctl_entry *rce)
-{
- if (!list_empty(&rce->rce_list))
- list_del(&rce->rce_list);
-
- kfree(rce);
-}
-
-static struct rmtacl_ctl_entry *__rct_search(struct rmtacl_ctl_table *rct,
- pid_t key)
-{
- struct rmtacl_ctl_entry *rce;
- struct list_head *head = &rct->rct_entries[rce_hashfunc(key)];
-
- list_for_each_entry(rce, head, rce_list)
- if (rce->rce_key == key)
- return rce;
-
- return NULL;
-}
-
-struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key)
-{
- struct rmtacl_ctl_entry *rce;
-
- spin_lock(&rct->rct_lock);
- rce = __rct_search(rct, key);
- spin_unlock(&rct->rct_lock);
- return rce;
-}
-
-int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops)
-{
- struct rmtacl_ctl_entry *rce, *e;
-
- rce = rce_alloc(key, ops);
- if (!rce)
- return -ENOMEM;
-
- spin_lock(&rct->rct_lock);
- e = __rct_search(rct, key);
- if (unlikely(e)) {
- CWARN("Unexpected stale rmtacl_entry found: [key: %d] [ops: %d]\n",
- (int)key, ops);
- rce_free(e);
- }
- list_add_tail(&rce->rce_list, &rct->rct_entries[rce_hashfunc(key)]);
- spin_unlock(&rct->rct_lock);
-
- return 0;
-}
-
-int rct_del(struct rmtacl_ctl_table *rct, pid_t key)
-{
- struct rmtacl_ctl_entry *rce;
-
- spin_lock(&rct->rct_lock);
- rce = __rct_search(rct, key);
- if (rce)
- rce_free(rce);
- spin_unlock(&rct->rct_lock);
-
- return rce ? 0 : -ENOENT;
-}
-
-void rct_init(struct rmtacl_ctl_table *rct)
-{
- int i;
-
- spin_lock_init(&rct->rct_lock);
- for (i = 0; i < RCE_HASHES; i++)
- INIT_LIST_HEAD(&rct->rct_entries[i]);
-}
-
-void rct_fini(struct rmtacl_ctl_table *rct)
-{
- struct rmtacl_ctl_entry *rce;
- int i;
-
- spin_lock(&rct->rct_lock);
- for (i = 0; i < RCE_HASHES; i++)
- while (!list_empty(&rct->rct_entries[i])) {
- rce = list_entry(rct->rct_entries[i].next,
- struct rmtacl_ctl_entry, rce_list);
- rce_free(rce);
- }
- spin_unlock(&rct->rct_lock);
-}
-
-static struct eacl_entry *ee_alloc(pid_t key, struct lu_fid *fid, int type,
- ext_acl_xattr_header *header)
-{
- struct eacl_entry *ee;
-
- ee = kzalloc(sizeof(*ee), GFP_NOFS);
- if (!ee)
- return NULL;
-
- INIT_LIST_HEAD(&ee->ee_list);
- ee->ee_key = key;
- ee->ee_fid = *fid;
- ee->ee_type = type;
- ee->ee_acl = header;
-
- return ee;
-}
-
-void ee_free(struct eacl_entry *ee)
-{
- if (!list_empty(&ee->ee_list))
- list_del(&ee->ee_list);
-
- if (ee->ee_acl)
- lustre_ext_acl_xattr_free(ee->ee_acl);
-
- kfree(ee);
-}
-
-static struct eacl_entry *__et_search_del(struct eacl_table *et, pid_t key,
- struct lu_fid *fid, int type)
-{
- struct eacl_entry *ee;
- struct list_head *head = &et->et_entries[ee_hashfunc(key)];
-
- LASSERT(fid);
- list_for_each_entry(ee, head, ee_list)
- if (ee->ee_key == key) {
- if (lu_fid_eq(&ee->ee_fid, fid) &&
- ee->ee_type == type) {
- list_del_init(&ee->ee_list);
- return ee;
- }
- }
-
- return NULL;
-}
-
-struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key,
- struct lu_fid *fid, int type)
-{
- struct eacl_entry *ee;
-
- spin_lock(&et->et_lock);
- ee = __et_search_del(et, key, fid, type);
- spin_unlock(&et->et_lock);
- return ee;
-}
-
-void et_search_free(struct eacl_table *et, pid_t key)
-{
- struct eacl_entry *ee, *next;
- struct list_head *head = &et->et_entries[ee_hashfunc(key)];
-
- spin_lock(&et->et_lock);
- list_for_each_entry_safe(ee, next, head, ee_list)
- if (ee->ee_key == key)
- ee_free(ee);
-
- spin_unlock(&et->et_lock);
-}
-
-int ee_add(struct eacl_table *et, pid_t key, struct lu_fid *fid, int type,
- ext_acl_xattr_header *header)
-{
- struct eacl_entry *ee, *e;
-
- ee = ee_alloc(key, fid, type, header);
- if (!ee)
- return -ENOMEM;
-
- spin_lock(&et->et_lock);
- e = __et_search_del(et, key, fid, type);
- if (unlikely(e)) {
- CWARN("Unexpected stale eacl_entry found: [key: %d] [fid: " DFID "] [type: %d]\n",
- (int)key, PFID(fid), type);
- ee_free(e);
- }
- list_add_tail(&ee->ee_list, &et->et_entries[ee_hashfunc(key)]);
- spin_unlock(&et->et_lock);
-
- return 0;
-}
-
-void et_init(struct eacl_table *et)
-{
- int i;
-
- spin_lock_init(&et->et_lock);
- for (i = 0; i < EE_HASHES; i++)
- INIT_LIST_HEAD(&et->et_entries[i]);
-}
-
-void et_fini(struct eacl_table *et)
-{
- struct eacl_entry *ee;
- int i;
-
- spin_lock(&et->et_lock);
- for (i = 0; i < EE_HASHES; i++)
- while (!list_empty(&et->et_entries[i])) {
- ee = list_entry(et->et_entries[i].next,
- struct eacl_entry, ee_list);
- ee_free(ee);
- }
- spin_unlock(&et->et_lock);
-}
-
-#endif
diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c
deleted file mode 100644
index 813a9a354..000000000
--- a/drivers/staging/lustre/lustre/llite/lloop.c
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-/*
- * linux/drivers/block/loop.c
- *
- * Written by Theodore Ts'o, 3/29/93
- *
- * Copyright 1993 by Theodore Ts'o. Redistribution of this file is
- * permitted under the GNU General Public License.
- *
- * Modularized and updated for 1.1.16 kernel - Mitch Dsouza 28th May 1994
- * Adapted for 1.3.59 kernel - Andries Brouwer, 1 Feb 1996
- *
- * Fixed do_loop_request() re-entrancy - Vincent.Renardias@waw.com Mar 20, 1997
- *
- * Added devfs support - Richard Gooch <rgooch@atnf.csiro.au> 16-Jan-1998
- *
- * Handle sparse backing files correctly - Kenn Humborg, Jun 28, 1998
- *
- * Loadable modules and other fixes by AK, 1998
- *
- * Maximum number of loop devices now dynamic via max_loop module parameter.
- * Russell Kroll <rkroll@exploits.org> 19990701
- *
- * Maximum number of loop devices when compiled-in now selectable by passing
- * max_loop=<1-255> to the kernel on boot.
- * Erik I. Bols?, <eriki@himolde.no>, Oct 31, 1999
- *
- * Completely rewrite request handling to be make_request_fn style and
- * non blocking, pushing work to a helper thread. Lots of fixes from
- * Al Viro too.
- * Jens Axboe <axboe@suse.de>, Nov 2000
- *
- * Support up to 256 loop devices
- * Heinz Mauelshagen <mge@sistina.com>, Feb 2002
- *
- * Support for falling back on the write file operation when the address space
- * operations prepare_write and/or commit_write are not available on the
- * backing filesystem.
- * Anton Altaparmakov, 16 Feb 2005
- *
- * Still To Fix:
- * - Advisory locking is ignored here.
- * - Should use an own CAP_* category instead of CAP_SYS_ADMIN
- *
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/major.h>
-#include <linux/wait.h>
-#include <linux/blkdev.h>
-#include <linux/blkpg.h>
-#include <linux/init.h>
-#include <linux/swap.h>
-#include <linux/slab.h>
-#include <linux/suspend.h>
-#include <linux/writeback.h>
-#include <linux/buffer_head.h> /* for invalidate_bdev() */
-#include <linux/completion.h>
-#include <linux/highmem.h>
-#include <linux/gfp.h>
-#include <linux/pagevec.h>
-#include <linux/uaccess.h>
-
-#include "../include/lustre_lib.h"
-#include "../include/lustre_lite.h"
-#include "llite_internal.h"
-
-#define LLOOP_MAX_SEGMENTS LNET_MAX_IOV
-
-/* Possible states of device */
-enum {
- LLOOP_UNBOUND,
- LLOOP_BOUND,
- LLOOP_RUNDOWN,
-};
-
-struct lloop_device {
- int lo_number;
- int lo_refcnt;
- loff_t lo_offset;
- loff_t lo_sizelimit;
- int lo_flags;
- struct file *lo_backing_file;
- struct block_device *lo_device;
- unsigned lo_blocksize;
-
- gfp_t old_gfp_mask;
-
- spinlock_t lo_lock;
- struct bio *lo_bio;
- struct bio *lo_biotail;
- int lo_state;
- struct semaphore lo_sem;
- struct mutex lo_ctl_mutex;
- atomic_t lo_pending;
- wait_queue_head_t lo_bh_wait;
-
- struct request_queue *lo_queue;
-
- const struct lu_env *lo_env;
- struct cl_io lo_io;
- struct ll_dio_pages lo_pvec;
-
- /* data to handle bio for lustre. */
- struct lo_request_data {
- struct page *lrd_pages[LLOOP_MAX_SEGMENTS];
- loff_t lrd_offsets[LLOOP_MAX_SEGMENTS];
- } lo_requests[1];
-};
-
-/*
- * Loop flags
- */
-enum {
- LO_FLAGS_READ_ONLY = 1,
-};
-
-static int lloop_major;
-#define MAX_LOOP_DEFAULT 16
-static int max_loop = MAX_LOOP_DEFAULT;
-static struct lloop_device *loop_dev;
-static struct gendisk **disks;
-static struct mutex lloop_mutex;
-static void *ll_iocontrol_magic;
-
-static loff_t get_loop_size(struct lloop_device *lo, struct file *file)
-{
- loff_t size, offset, loopsize;
-
- /* Compute loopsize in bytes */
- size = i_size_read(file->f_mapping->host);
- offset = lo->lo_offset;
- loopsize = size - offset;
- if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)
- loopsize = lo->lo_sizelimit;
-
- /*
- * Unfortunately, if we want to do I/O on the device,
- * the number of 512-byte sectors has to fit into a sector_t.
- */
- return loopsize >> 9;
-}
-
-static int do_bio_lustrebacked(struct lloop_device *lo, struct bio *head)
-{
- const struct lu_env *env = lo->lo_env;
- struct cl_io *io = &lo->lo_io;
- struct inode *inode = file_inode(lo->lo_backing_file);
- struct cl_object *obj = ll_i2info(inode)->lli_clob;
- pgoff_t offset;
- int ret;
- int rw;
- u32 page_count = 0;
- struct bio_vec bvec;
- struct bvec_iter iter;
- struct bio *bio;
- ssize_t bytes;
-
- struct ll_dio_pages *pvec = &lo->lo_pvec;
- struct page **pages = pvec->ldp_pages;
- loff_t *offsets = pvec->ldp_offsets;
-
- truncate_inode_pages(inode->i_mapping, 0);
-
- /* initialize the IO */
- memset(io, 0, sizeof(*io));
- io->ci_obj = obj;
- ret = cl_io_init(env, io, CIT_MISC, obj);
- if (ret)
- return io->ci_result;
- io->ci_lockreq = CILR_NEVER;
-
- rw = head->bi_rw;
- for (bio = head; bio ; bio = bio->bi_next) {
- LASSERT(rw == bio->bi_rw);
-
- offset = (pgoff_t)(bio->bi_iter.bi_sector << 9) + lo->lo_offset;
- bio_for_each_segment(bvec, bio, iter) {
- BUG_ON(bvec.bv_offset != 0);
- BUG_ON(bvec.bv_len != PAGE_SIZE);
-
- pages[page_count] = bvec.bv_page;
- offsets[page_count] = offset;
- page_count++;
- offset += bvec.bv_len;
- }
- LASSERT(page_count <= LLOOP_MAX_SEGMENTS);
- }
-
- ll_stats_ops_tally(ll_i2sbi(inode),
- (rw == WRITE) ? LPROC_LL_BRW_WRITE : LPROC_LL_BRW_READ,
- page_count);
-
- pvec->ldp_size = page_count << PAGE_SHIFT;
- pvec->ldp_nr = page_count;
-
- /* FIXME: in ll_direct_rw_pages, it has to allocate many cl_page{}s to
- * write those pages into OST. Even worse case is that more pages
- * would be asked to write out to swap space, and then finally get here
- * again.
- * Unfortunately this is NOT easy to fix.
- * Thoughts on solution:
- * 0. Define a reserved pool for cl_pages, which could be a list of
- * pre-allocated cl_pages;
- * 1. Define a new operation in cl_object_operations{}, says clo_depth,
- * which measures how many layers for this lustre object. Generally
- * speaking, the depth would be 2, one for llite, and one for lovsub.
- * However, for SNS, there will be more since we need additional page
- * to store parity;
- * 2. Reserve the # of (page_count * depth) cl_pages from the reserved
- * pool. Afterwards, the clio would allocate the pages from reserved
- * pool, this guarantees we needn't allocate the cl_pages from
- * generic cl_page slab cache.
- * Of course, if there is NOT enough pages in the pool, we might
- * be asked to write less pages once, this purely depends on
- * implementation. Anyway, we should be careful to avoid deadlocking.
- */
- inode_lock(inode);
- bytes = ll_direct_rw_pages(env, io, rw, inode, pvec);
- inode_unlock(inode);
- cl_io_fini(env, io);
- return (bytes == pvec->ldp_size) ? 0 : (int)bytes;
-}
-
-/*
- * Add bio to back of pending list
- */
-static void loop_add_bio(struct lloop_device *lo, struct bio *bio)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&lo->lo_lock, flags);
- if (lo->lo_biotail) {
- lo->lo_biotail->bi_next = bio;
- lo->lo_biotail = bio;
- } else {
- lo->lo_bio = lo->lo_biotail = bio;
- }
- spin_unlock_irqrestore(&lo->lo_lock, flags);
-
- atomic_inc(&lo->lo_pending);
- if (waitqueue_active(&lo->lo_bh_wait))
- wake_up(&lo->lo_bh_wait);
-}
-
-/*
- * Grab first pending buffer
- */
-static unsigned int loop_get_bio(struct lloop_device *lo, struct bio **req)
-{
- struct bio *first;
- struct bio **bio;
- unsigned int count = 0;
- unsigned int page_count = 0;
- int rw;
-
- spin_lock_irq(&lo->lo_lock);
- first = lo->lo_bio;
- if (unlikely(!first)) {
- spin_unlock_irq(&lo->lo_lock);
- return 0;
- }
-
- /* TODO: need to split the bio, too bad. */
- LASSERT(first->bi_vcnt <= LLOOP_MAX_SEGMENTS);
-
- rw = first->bi_rw;
- bio = &lo->lo_bio;
- while (*bio && (*bio)->bi_rw == rw) {
- CDEBUG(D_INFO, "bio sector %llu size %u count %u vcnt%u\n",
- (unsigned long long)(*bio)->bi_iter.bi_sector,
- (*bio)->bi_iter.bi_size,
- page_count, (*bio)->bi_vcnt);
- if (page_count + (*bio)->bi_vcnt > LLOOP_MAX_SEGMENTS)
- break;
-
- page_count += (*bio)->bi_vcnt;
- count++;
- bio = &(*bio)->bi_next;
- }
- if (*bio) {
- /* Some of bios can't be mergeable. */
- lo->lo_bio = *bio;
- *bio = NULL;
- } else {
- /* Hit the end of queue */
- lo->lo_biotail = NULL;
- lo->lo_bio = NULL;
- }
- *req = first;
- spin_unlock_irq(&lo->lo_lock);
- return count;
-}
-
-static blk_qc_t loop_make_request(struct request_queue *q, struct bio *old_bio)
-{
- struct lloop_device *lo = q->queuedata;
- int rw = bio_rw(old_bio);
- int inactive;
-
- blk_queue_split(q, &old_bio, q->bio_split);
-
- if (!lo)
- goto err;
-
- CDEBUG(D_INFO, "submit bio sector %llu size %u\n",
- (unsigned long long)old_bio->bi_iter.bi_sector,
- old_bio->bi_iter.bi_size);
-
- spin_lock_irq(&lo->lo_lock);
- inactive = lo->lo_state != LLOOP_BOUND;
- spin_unlock_irq(&lo->lo_lock);
- if (inactive)
- goto err;
-
- if (rw == WRITE) {
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
- rw = READ;
- } else if (rw != READ) {
- CERROR("lloop: unknown command (%x)\n", rw);
- goto err;
- }
- loop_add_bio(lo, old_bio);
- return BLK_QC_T_NONE;
-err:
- bio_io_error(old_bio);
- return BLK_QC_T_NONE;
-}
-
-static inline void loop_handle_bio(struct lloop_device *lo, struct bio *bio)
-{
- int ret;
-
- ret = do_bio_lustrebacked(lo, bio);
- while (bio) {
- struct bio *tmp = bio->bi_next;
-
- bio->bi_next = NULL;
- bio->bi_error = ret;
- bio_endio(bio);
- bio = tmp;
- }
-}
-
-static inline int loop_active(struct lloop_device *lo)
-{
- return atomic_read(&lo->lo_pending) ||
- (lo->lo_state == LLOOP_RUNDOWN);
-}
-
-/*
- * worker thread that handles reads/writes to file backed loop devices,
- * to avoid blocking in our make_request_fn.
- */
-static int loop_thread(void *data)
-{
- struct lloop_device *lo = data;
- struct bio *bio;
- unsigned int count;
- unsigned long times = 0;
- unsigned long total_count = 0;
-
- struct lu_env *env;
- int refcheck;
- int ret = 0;
-
- set_user_nice(current, MIN_NICE);
-
- lo->lo_state = LLOOP_BOUND;
-
- env = cl_env_get(&refcheck);
- if (IS_ERR(env)) {
- ret = PTR_ERR(env);
- goto out;
- }
-
- lo->lo_env = env;
- memset(&lo->lo_pvec, 0, sizeof(lo->lo_pvec));
- lo->lo_pvec.ldp_pages = lo->lo_requests[0].lrd_pages;
- lo->lo_pvec.ldp_offsets = lo->lo_requests[0].lrd_offsets;
-
- /*
- * up sem, we are running
- */
- up(&lo->lo_sem);
-
- for (;;) {
- wait_event(lo->lo_bh_wait, loop_active(lo));
- if (!atomic_read(&lo->lo_pending)) {
- int exiting = 0;
-
- spin_lock_irq(&lo->lo_lock);
- exiting = (lo->lo_state == LLOOP_RUNDOWN);
- spin_unlock_irq(&lo->lo_lock);
- if (exiting)
- break;
- }
-
- bio = NULL;
- count = loop_get_bio(lo, &bio);
- if (!count) {
- CWARN("lloop(minor: %d): missing bio\n", lo->lo_number);
- continue;
- }
-
- total_count += count;
- if (total_count < count) { /* overflow */
- total_count = count;
- times = 1;
- } else {
- times++;
- }
- if ((times & 127) == 0) {
- CDEBUG(D_INFO, "total: %lu, count: %lu, avg: %lu\n",
- total_count, times, total_count / times);
- }
-
- LASSERT(bio);
- LASSERT(count <= atomic_read(&lo->lo_pending));
- loop_handle_bio(lo, bio);
- atomic_sub(count, &lo->lo_pending);
- }
- cl_env_put(env, &refcheck);
-
-out:
- up(&lo->lo_sem);
- return ret;
-}
-
-static int loop_set_fd(struct lloop_device *lo, struct file *unused,
- struct block_device *bdev, struct file *file)
-{
- struct inode *inode;
- struct address_space *mapping;
- int lo_flags = 0;
- int error;
- loff_t size;
-
- if (!try_module_get(THIS_MODULE))
- return -ENODEV;
-
- error = -EBUSY;
- if (lo->lo_state != LLOOP_UNBOUND)
- goto out;
-
- mapping = file->f_mapping;
- inode = mapping->host;
-
- error = -EINVAL;
- if (!S_ISREG(inode->i_mode) || inode->i_sb->s_magic != LL_SUPER_MAGIC)
- goto out;
-
- if (!(file->f_mode & FMODE_WRITE))
- lo_flags |= LO_FLAGS_READ_ONLY;
-
- size = get_loop_size(lo, file);
-
- if ((loff_t)(sector_t)size != size) {
- error = -EFBIG;
- goto out;
- }
-
- /* remove all pages in cache so as dirty pages not to be existent. */
- truncate_inode_pages(mapping, 0);
-
- set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);
-
- lo->lo_blocksize = PAGE_SIZE;
- lo->lo_device = bdev;
- lo->lo_flags = lo_flags;
- lo->lo_backing_file = file;
- lo->lo_sizelimit = 0;
- lo->old_gfp_mask = mapping_gfp_mask(mapping);
- mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
-
- lo->lo_bio = lo->lo_biotail = NULL;
-
- /*
- * set queue make_request_fn, and add limits based on lower level
- * device
- */
- blk_queue_make_request(lo->lo_queue, loop_make_request);
- lo->lo_queue->queuedata = lo;
-
- /* queue parameters */
- CLASSERT(PAGE_SIZE < (1 << (sizeof(unsigned short) * 8)));
- blk_queue_logical_block_size(lo->lo_queue,
- (unsigned short)PAGE_SIZE);
- blk_queue_max_hw_sectors(lo->lo_queue,
- LLOOP_MAX_SEGMENTS << (PAGE_SHIFT - 9));
- blk_queue_max_segments(lo->lo_queue, LLOOP_MAX_SEGMENTS);
-
- set_capacity(disks[lo->lo_number], size);
- bd_set_size(bdev, size << 9);
-
- set_blocksize(bdev, lo->lo_blocksize);
-
- kthread_run(loop_thread, lo, "lloop%d", lo->lo_number);
- down(&lo->lo_sem);
- return 0;
-
-out:
- /* This is safe: open() is still holding a reference. */
- module_put(THIS_MODULE);
- return error;
-}
-
-static int loop_clr_fd(struct lloop_device *lo, struct block_device *bdev,
- int count)
-{
- struct file *filp = lo->lo_backing_file;
- gfp_t gfp = lo->old_gfp_mask;
-
- if (lo->lo_state != LLOOP_BOUND)
- return -ENXIO;
-
- if (lo->lo_refcnt > count) /* we needed one fd for the ioctl */
- return -EBUSY;
-
- if (!filp)
- return -EINVAL;
-
- spin_lock_irq(&lo->lo_lock);
- lo->lo_state = LLOOP_RUNDOWN;
- spin_unlock_irq(&lo->lo_lock);
- wake_up(&lo->lo_bh_wait);
-
- down(&lo->lo_sem);
- lo->lo_backing_file = NULL;
- lo->lo_device = NULL;
- lo->lo_offset = 0;
- lo->lo_sizelimit = 0;
- lo->lo_flags = 0;
- invalidate_bdev(bdev);
- set_capacity(disks[lo->lo_number], 0);
- bd_set_size(bdev, 0);
- mapping_set_gfp_mask(filp->f_mapping, gfp);
- lo->lo_state = LLOOP_UNBOUND;
- fput(filp);
- /* This is safe: open() is still holding a reference. */
- module_put(THIS_MODULE);
- return 0;
-}
-
-static int lo_open(struct block_device *bdev, fmode_t mode)
-{
- struct lloop_device *lo = bdev->bd_disk->private_data;
-
- mutex_lock(&lo->lo_ctl_mutex);
- lo->lo_refcnt++;
- mutex_unlock(&lo->lo_ctl_mutex);
-
- return 0;
-}
-
-static void lo_release(struct gendisk *disk, fmode_t mode)
-{
- struct lloop_device *lo = disk->private_data;
-
- mutex_lock(&lo->lo_ctl_mutex);
- --lo->lo_refcnt;
- mutex_unlock(&lo->lo_ctl_mutex);
-}
-
-/* lloop device node's ioctl function. */
-static int lo_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- struct lloop_device *lo = bdev->bd_disk->private_data;
- struct inode *inode = NULL;
- int err = 0;
-
- mutex_lock(&lloop_mutex);
- switch (cmd) {
- case LL_IOC_LLOOP_DETACH: {
- err = loop_clr_fd(lo, bdev, 2);
- if (err == 0)
- blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */
- break;
- }
-
- case LL_IOC_LLOOP_INFO: {
- struct lu_fid fid;
-
- if (!lo->lo_backing_file) {
- err = -ENOENT;
- break;
- }
- if (!inode)
- inode = file_inode(lo->lo_backing_file);
- if (lo->lo_state == LLOOP_BOUND)
- fid = ll_i2info(inode)->lli_fid;
- else
- fid_zero(&fid);
-
- if (copy_to_user((void __user *)arg, &fid, sizeof(fid)))
- err = -EFAULT;
- break;
- }
-
- default:
- err = -EINVAL;
- break;
- }
- mutex_unlock(&lloop_mutex);
-
- return err;
-}
-
-static struct block_device_operations lo_fops = {
- .owner = THIS_MODULE,
- .open = lo_open,
- .release = lo_release,
- .ioctl = lo_ioctl,
-};
-
-/* dynamic iocontrol callback.
- * This callback is registered in lloop_init and will be called by
- * ll_iocontrol_call.
- *
- * This is a llite regular file ioctl function. It takes the responsibility
- * of attaching or detaching a file by a lloop's device number.
- */
-static enum llioc_iter lloop_ioctl(struct inode *unused, struct file *file,
- unsigned int cmd, unsigned long arg,
- void *magic, int *rcp)
-{
- struct lloop_device *lo = NULL;
- struct block_device *bdev = NULL;
- int err = 0;
- dev_t dev;
-
- if (magic != ll_iocontrol_magic)
- return LLIOC_CONT;
-
- if (!disks) {
- err = -ENODEV;
- goto out1;
- }
-
- CWARN("Enter llop_ioctl\n");
-
- mutex_lock(&lloop_mutex);
- switch (cmd) {
- case LL_IOC_LLOOP_ATTACH: {
- struct lloop_device *lo_free = NULL;
- int i;
-
- for (i = 0; i < max_loop; i++, lo = NULL) {
- lo = &loop_dev[i];
- if (lo->lo_state == LLOOP_UNBOUND) {
- if (!lo_free)
- lo_free = lo;
- continue;
- }
- if (file_inode(lo->lo_backing_file) == file_inode(file))
- break;
- }
- if (lo || !lo_free) {
- err = -EBUSY;
- goto out;
- }
-
- lo = lo_free;
- dev = MKDEV(lloop_major, lo->lo_number);
-
- /* quit if the used pointer is writable */
- if (put_user((long)old_encode_dev(dev), (long __user *)arg)) {
- err = -EFAULT;
- goto out;
- }
-
- bdev = blkdev_get_by_dev(dev, file->f_mode, NULL);
- if (IS_ERR(bdev)) {
- err = PTR_ERR(bdev);
- goto out;
- }
-
- get_file(file);
- err = loop_set_fd(lo, NULL, bdev, file);
- if (err) {
- fput(file);
- blkdev_put(bdev, 0);
- }
-
- break;
- }
-
- case LL_IOC_LLOOP_DETACH_BYDEV: {
- int minor;
-
- dev = old_decode_dev(arg);
- if (MAJOR(dev) != lloop_major) {
- err = -EINVAL;
- goto out;
- }
-
- minor = MINOR(dev);
- if (minor > max_loop - 1) {
- err = -EINVAL;
- goto out;
- }
-
- lo = &loop_dev[minor];
- if (lo->lo_state != LLOOP_BOUND) {
- err = -EINVAL;
- goto out;
- }
-
- bdev = lo->lo_device;
- err = loop_clr_fd(lo, bdev, 1);
- if (err == 0)
- blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */
-
- break;
- }
-
- default:
- err = -EINVAL;
- break;
- }
-
-out:
- mutex_unlock(&lloop_mutex);
-out1:
- if (rcp)
- *rcp = err;
- return LLIOC_STOP;
-}
-
-static int __init lloop_init(void)
-{
- int i;
- unsigned int cmdlist[] = {
- LL_IOC_LLOOP_ATTACH,
- LL_IOC_LLOOP_DETACH_BYDEV,
- };
-
- if (max_loop < 1 || max_loop > 256) {
- max_loop = MAX_LOOP_DEFAULT;
- CWARN("lloop: invalid max_loop (must be between 1 and 256), using default (%u)\n",
- max_loop);
- }
-
- lloop_major = register_blkdev(0, "lloop");
- if (lloop_major < 0)
- return -EIO;
-
- CDEBUG(D_CONFIG, "registered lloop major %d with %u minors\n",
- lloop_major, max_loop);
-
- ll_iocontrol_magic = ll_iocontrol_register(lloop_ioctl, 2, cmdlist);
- if (!ll_iocontrol_magic)
- goto out_mem1;
-
- loop_dev = kcalloc(max_loop, sizeof(*loop_dev), GFP_KERNEL);
- if (!loop_dev)
- goto out_mem1;
-
- disks = kcalloc(max_loop, sizeof(*disks), GFP_KERNEL);
- if (!disks)
- goto out_mem2;
-
- for (i = 0; i < max_loop; i++) {
- disks[i] = alloc_disk(1);
- if (!disks[i])
- goto out_mem3;
- }
-
- mutex_init(&lloop_mutex);
-
- for (i = 0; i < max_loop; i++) {
- struct lloop_device *lo = &loop_dev[i];
- struct gendisk *disk = disks[i];
-
- lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
- if (!lo->lo_queue)
- goto out_mem4;
-
- mutex_init(&lo->lo_ctl_mutex);
- sema_init(&lo->lo_sem, 0);
- init_waitqueue_head(&lo->lo_bh_wait);
- lo->lo_number = i;
- spin_lock_init(&lo->lo_lock);
- disk->major = lloop_major;
- disk->first_minor = i;
- disk->fops = &lo_fops;
- sprintf(disk->disk_name, "lloop%d", i);
- disk->private_data = lo;
- disk->queue = lo->lo_queue;
- }
-
- /* We cannot fail after we call this, so another loop!*/
- for (i = 0; i < max_loop; i++)
- add_disk(disks[i]);
- return 0;
-
-out_mem4:
- while (i--)
- blk_cleanup_queue(loop_dev[i].lo_queue);
- i = max_loop;
-out_mem3:
- while (i--)
- put_disk(disks[i]);
- kfree(disks);
-out_mem2:
- kfree(loop_dev);
-out_mem1:
- unregister_blkdev(lloop_major, "lloop");
- ll_iocontrol_unregister(ll_iocontrol_magic);
- CERROR("lloop: ran out of memory\n");
- return -ENOMEM;
-}
-
-static void lloop_exit(void)
-{
- int i;
-
- ll_iocontrol_unregister(ll_iocontrol_magic);
- for (i = 0; i < max_loop; i++) {
- del_gendisk(disks[i]);
- blk_cleanup_queue(loop_dev[i].lo_queue);
- put_disk(disks[i]);
- }
-
- unregister_blkdev(lloop_major, "lloop");
-
- kfree(disks);
- kfree(loop_dev);
-}
-
-module_param(max_loop, int, 0444);
-MODULE_PARM_DESC(max_loop, "maximum of lloop_device");
-MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
-MODULE_DESCRIPTION("Lustre virtual block device");
-MODULE_VERSION(LUSTRE_VERSION_STRING);
-MODULE_LICENSE("GPL");
-
-module_init(lloop_init);
-module_exit(lloop_exit);
diff --git a/drivers/staging/lustre/lustre/llite/remote_perm.c b/drivers/staging/lustre/lustre/llite/remote_perm.c
deleted file mode 100644
index e9d25317c..000000000
--- a/drivers/staging/lustre/lustre/llite/remote_perm.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/llite/remote_perm.c
- *
- * Lustre Permission Cache for Remote Client
- *
- * Author: Lai Siyao <lsy@clusterfs.com>
- * Author: Fan Yong <fanyong@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/module.h>
-#include <linux/types.h>
-
-#include "../include/lustre_lite.h"
-#include "../include/lustre_ha.h"
-#include "../include/lustre_dlm.h"
-#include "../include/lprocfs_status.h"
-#include "../include/lustre_disk.h"
-#include "../include/lustre_param.h"
-#include "llite_internal.h"
-
-struct kmem_cache *ll_remote_perm_cachep;
-struct kmem_cache *ll_rmtperm_hash_cachep;
-
-static inline struct ll_remote_perm *alloc_ll_remote_perm(void)
-{
- struct ll_remote_perm *lrp;
-
- lrp = kmem_cache_zalloc(ll_remote_perm_cachep, GFP_KERNEL);
- if (lrp)
- INIT_HLIST_NODE(&lrp->lrp_list);
- return lrp;
-}
-
-static inline void free_ll_remote_perm(struct ll_remote_perm *lrp)
-{
- if (!lrp)
- return;
-
- if (!hlist_unhashed(&lrp->lrp_list))
- hlist_del(&lrp->lrp_list);
- kmem_cache_free(ll_remote_perm_cachep, lrp);
-}
-
-static struct hlist_head *alloc_rmtperm_hash(void)
-{
- struct hlist_head *hash;
- int i;
-
- hash = kmem_cache_zalloc(ll_rmtperm_hash_cachep, GFP_NOFS);
- if (!hash)
- return NULL;
-
- for (i = 0; i < REMOTE_PERM_HASHSIZE; i++)
- INIT_HLIST_HEAD(hash + i);
-
- return hash;
-}
-
-void free_rmtperm_hash(struct hlist_head *hash)
-{
- int i;
- struct ll_remote_perm *lrp;
- struct hlist_node *next;
-
- if (!hash)
- return;
-
- for (i = 0; i < REMOTE_PERM_HASHSIZE; i++)
- hlist_for_each_entry_safe(lrp, next, hash + i, lrp_list)
- free_ll_remote_perm(lrp);
- kmem_cache_free(ll_rmtperm_hash_cachep, hash);
-}
-
-static inline int remote_perm_hashfunc(uid_t uid)
-{
- return uid & (REMOTE_PERM_HASHSIZE - 1);
-}
-
-/* NB: setxid permission is not checked here, instead it's done on
- * MDT when client get remote permission.
- */
-static int do_check_remote_perm(struct ll_inode_info *lli, int mask)
-{
- struct hlist_head *head;
- struct ll_remote_perm *lrp;
- int found = 0, rc;
-
- if (!lli->lli_remote_perms)
- return -ENOENT;
-
- head = lli->lli_remote_perms +
- remote_perm_hashfunc(from_kuid(&init_user_ns, current_uid()));
-
- spin_lock(&lli->lli_lock);
- hlist_for_each_entry(lrp, head, lrp_list) {
- if (lrp->lrp_uid != from_kuid(&init_user_ns, current_uid()))
- continue;
- if (lrp->lrp_gid != from_kgid(&init_user_ns, current_gid()))
- continue;
- if (lrp->lrp_fsuid != from_kuid(&init_user_ns, current_fsuid()))
- continue;
- if (lrp->lrp_fsgid != from_kgid(&init_user_ns, current_fsgid()))
- continue;
- found = 1;
- break;
- }
-
- if (!found) {
- rc = -ENOENT;
- goto out;
- }
-
- CDEBUG(D_SEC, "found remote perm: %u/%u/%u/%u - %#x\n",
- lrp->lrp_uid, lrp->lrp_gid, lrp->lrp_fsuid, lrp->lrp_fsgid,
- lrp->lrp_access_perm);
- rc = ((lrp->lrp_access_perm & mask) == mask) ? 0 : -EACCES;
-
-out:
- spin_unlock(&lli->lli_lock);
- return rc;
-}
-
-int ll_update_remote_perm(struct inode *inode, struct mdt_remote_perm *perm)
-{
- struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_remote_perm *lrp = NULL, *tmp = NULL;
- struct hlist_head *head, *perm_hash = NULL;
-
- LASSERT(ll_i2sbi(inode)->ll_flags & LL_SBI_RMT_CLIENT);
-
-#if 0
- if (perm->rp_uid != current->uid ||
- perm->rp_gid != current->gid ||
- perm->rp_fsuid != current->fsuid ||
- perm->rp_fsgid != current->fsgid) {
- /* user might setxid in this small period */
- CDEBUG(D_SEC,
- "remote perm user %u/%u/%u/%u != current %u/%u/%u/%u\n",
- perm->rp_uid, perm->rp_gid, perm->rp_fsuid,
- perm->rp_fsgid, current->uid, current->gid,
- current->fsuid, current->fsgid);
- return -EAGAIN;
- }
-#endif
-
- if (!lli->lli_remote_perms) {
- perm_hash = alloc_rmtperm_hash();
- if (!perm_hash) {
- CERROR("alloc lli_remote_perms failed!\n");
- return -ENOMEM;
- }
- }
-
- spin_lock(&lli->lli_lock);
-
- if (!lli->lli_remote_perms)
- lli->lli_remote_perms = perm_hash;
- else
- free_rmtperm_hash(perm_hash);
-
- head = lli->lli_remote_perms + remote_perm_hashfunc(perm->rp_uid);
-
-again:
- hlist_for_each_entry(tmp, head, lrp_list) {
- if (tmp->lrp_uid != perm->rp_uid)
- continue;
- if (tmp->lrp_gid != perm->rp_gid)
- continue;
- if (tmp->lrp_fsuid != perm->rp_fsuid)
- continue;
- if (tmp->lrp_fsgid != perm->rp_fsgid)
- continue;
- free_ll_remote_perm(lrp);
- lrp = tmp;
- break;
- }
-
- if (!lrp) {
- spin_unlock(&lli->lli_lock);
- lrp = alloc_ll_remote_perm();
- if (!lrp) {
- CERROR("alloc memory for ll_remote_perm failed!\n");
- return -ENOMEM;
- }
- spin_lock(&lli->lli_lock);
- goto again;
- }
-
- lrp->lrp_access_perm = perm->rp_access_perm;
- if (lrp != tmp) {
- lrp->lrp_uid = perm->rp_uid;
- lrp->lrp_gid = perm->rp_gid;
- lrp->lrp_fsuid = perm->rp_fsuid;
- lrp->lrp_fsgid = perm->rp_fsgid;
- hlist_add_head(&lrp->lrp_list, head);
- }
- lli->lli_rmtperm_time = cfs_time_current();
- spin_unlock(&lli->lli_lock);
-
- CDEBUG(D_SEC, "new remote perm@%p: %u/%u/%u/%u - %#x\n",
- lrp, lrp->lrp_uid, lrp->lrp_gid, lrp->lrp_fsuid, lrp->lrp_fsgid,
- lrp->lrp_access_perm);
-
- return 0;
-}
-
-int lustre_check_remote_perm(struct inode *inode, int mask)
-{
- struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ptlrpc_request *req = NULL;
- struct mdt_remote_perm *perm;
- unsigned long save;
- int i = 0, rc;
-
- do {
- save = lli->lli_rmtperm_time;
- rc = do_check_remote_perm(lli, mask);
- if (!rc || (rc != -ENOENT && i))
- break;
-
- might_sleep();
-
- mutex_lock(&lli->lli_rmtperm_mutex);
- /* check again */
- if (save != lli->lli_rmtperm_time) {
- rc = do_check_remote_perm(lli, mask);
- if (!rc || (rc != -ENOENT && i)) {
- mutex_unlock(&lli->lli_rmtperm_mutex);
- break;
- }
- }
-
- if (i++ > 5) {
- CERROR("check remote perm falls in dead loop!\n");
- LBUG();
- }
-
- rc = md_get_remote_perm(sbi->ll_md_exp, ll_inode2fid(inode),
- ll_i2suppgid(inode), &req);
- if (rc) {
- mutex_unlock(&lli->lli_rmtperm_mutex);
- break;
- }
-
- perm = req_capsule_server_swab_get(&req->rq_pill, &RMF_ACL,
- lustre_swab_mdt_remote_perm);
- if (unlikely(!perm)) {
- mutex_unlock(&lli->lli_rmtperm_mutex);
- rc = -EPROTO;
- break;
- }
-
- rc = ll_update_remote_perm(inode, perm);
- mutex_unlock(&lli->lli_rmtperm_mutex);
- if (rc == -ENOMEM)
- break;
-
- ptlrpc_req_finished(req);
- req = NULL;
- } while (1);
- ptlrpc_req_finished(req);
- return rc;
-}
-
-#if 0 /* NB: remote perms can't be freed in ll_mdc_blocking_ast of UPDATE lock,
- * because it will fail sanity test 48.
- */
-void ll_free_remote_perms(struct inode *inode)
-{
- struct ll_inode_info *lli = ll_i2info(inode);
- struct hlist_head *hash = lli->lli_remote_perms;
- struct ll_remote_perm *lrp;
- struct hlist_node *node, *next;
- int i;
-
- LASSERT(hash);
-
- spin_lock(&lli->lli_lock);
-
- for (i = 0; i < REMOTE_PERM_HASHSIZE; i++) {
- hlist_for_each_entry_safe(lrp, node, next, hash + i, lrp_list)
- free_ll_remote_perm(lrp);
- }
-
- spin_unlock(&lli->lli_lock);
-}
-#endif
diff --git a/drivers/staging/lustre/lustre/obdclass/acl.c b/drivers/staging/lustre/lustre/obdclass/acl.c
deleted file mode 100644
index 0e02ae97b..000000000
--- a/drivers/staging/lustre/lustre/obdclass/acl.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/acl.c
- *
- * Lustre Access Control List.
- *
- * Author: Fan Yong <fanyong@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_SEC
-#include "../include/lu_object.h"
-#include "../include/lustre_acl.h"
-#include "../include/lustre_eacl.h"
-#include "../include/obd_support.h"
-
-#ifdef CONFIG_FS_POSIX_ACL
-
-#define CFS_ACL_XATTR_VERSION POSIX_ACL_XATTR_VERSION
-
-enum {
- ES_UNK = 0, /* unknown stat */
- ES_UNC = 1, /* ACL entry is not changed */
- ES_MOD = 2, /* ACL entry is modified */
- ES_ADD = 3, /* ACL entry is added */
- ES_DEL = 4 /* ACL entry is deleted */
-};
-
-static inline void lustre_ext_acl_le_to_cpu(ext_acl_xattr_entry *d,
- ext_acl_xattr_entry *s)
-{
- d->e_tag = le16_to_cpu(s->e_tag);
- d->e_perm = le16_to_cpu(s->e_perm);
- d->e_id = le32_to_cpu(s->e_id);
- d->e_stat = le32_to_cpu(s->e_stat);
-}
-
-static inline void lustre_ext_acl_cpu_to_le(ext_acl_xattr_entry *d,
- ext_acl_xattr_entry *s)
-{
- d->e_tag = cpu_to_le16(s->e_tag);
- d->e_perm = cpu_to_le16(s->e_perm);
- d->e_id = cpu_to_le32(s->e_id);
- d->e_stat = cpu_to_le32(s->e_stat);
-}
-
-static inline void lustre_posix_acl_le_to_cpu(posix_acl_xattr_entry *d,
- posix_acl_xattr_entry *s)
-{
- d->e_tag = le16_to_cpu(s->e_tag);
- d->e_perm = le16_to_cpu(s->e_perm);
- d->e_id = le32_to_cpu(s->e_id);
-}
-
-static inline void lustre_posix_acl_cpu_to_le(posix_acl_xattr_entry *d,
- posix_acl_xattr_entry *s)
-{
- d->e_tag = cpu_to_le16(s->e_tag);
- d->e_perm = cpu_to_le16(s->e_perm);
- d->e_id = cpu_to_le32(s->e_id);
-}
-
-/* if "new_count == 0", then "new = {a_version, NULL}", NOT NULL. */
-static int lustre_posix_acl_xattr_reduce_space(posix_acl_xattr_header **header,
- int old_count, int new_count)
-{
- int old_size = CFS_ACL_XATTR_SIZE(old_count, posix_acl_xattr);
- int new_size = CFS_ACL_XATTR_SIZE(new_count, posix_acl_xattr);
- posix_acl_xattr_header *new;
-
- if (unlikely(old_count <= new_count))
- return old_size;
-
- new = kmemdup(*header, new_size, GFP_NOFS);
- if (unlikely(!new))
- return -ENOMEM;
-
- kfree(*header);
- *header = new;
- return new_size;
-}
-
-/* if "new_count == 0", then "new = {0, NULL}", NOT NULL. */
-static int lustre_ext_acl_xattr_reduce_space(ext_acl_xattr_header **header,
- int old_count)
-{
- int ext_count = le32_to_cpu((*header)->a_count);
- int ext_size = CFS_ACL_XATTR_SIZE(ext_count, ext_acl_xattr);
- ext_acl_xattr_header *new;
-
- if (unlikely(old_count <= ext_count))
- return 0;
-
- new = kmemdup(*header, ext_size, GFP_NOFS);
- if (unlikely(!new))
- return -ENOMEM;
-
- kfree(*header);
- *header = new;
- return 0;
-}
-
-/*
- * Generate new extended ACL based on the posix ACL.
- */
-ext_acl_xattr_header *
-lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size)
-{
- int count, i, esize;
- ext_acl_xattr_header *new;
-
- if (unlikely(size < 0))
- return ERR_PTR(-EINVAL);
- else if (!size)
- count = 0;
- else
- count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
- esize = CFS_ACL_XATTR_SIZE(count, ext_acl_xattr);
- new = kzalloc(esize, GFP_NOFS);
- if (unlikely(!new))
- return ERR_PTR(-ENOMEM);
-
- new->a_count = cpu_to_le32(count);
- for (i = 0; i < count; i++) {
- new->a_entries[i].e_tag = header->a_entries[i].e_tag;
- new->a_entries[i].e_perm = header->a_entries[i].e_perm;
- new->a_entries[i].e_id = header->a_entries[i].e_id;
- new->a_entries[i].e_stat = cpu_to_le32(ES_UNK);
- }
-
- return new;
-}
-EXPORT_SYMBOL(lustre_posix_acl_xattr_2ext);
-
-/*
- * Filter out the "nobody" entries in the posix ACL.
- */
-int lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, size_t size,
- posix_acl_xattr_header **out)
-{
- int count, i, j, rc = 0;
- __u32 id;
- posix_acl_xattr_header *new;
-
- if (!size)
- return 0;
- if (size < sizeof(*new))
- return -EINVAL;
-
- new = kzalloc(size, GFP_NOFS);
- if (unlikely(!new))
- return -ENOMEM;
-
- new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
- count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
- for (i = 0, j = 0; i < count; i++) {
- id = le32_to_cpu(header->a_entries[i].e_id);
- switch (le16_to_cpu(header->a_entries[i].e_tag)) {
- case ACL_USER_OBJ:
- case ACL_GROUP_OBJ:
- case ACL_MASK:
- case ACL_OTHER:
- if (id != ACL_UNDEFINED_ID) {
- rc = -EIO;
- goto _out;
- }
-
- memcpy(&new->a_entries[j++], &header->a_entries[i],
- sizeof(posix_acl_xattr_entry));
- break;
- case ACL_USER:
- if (id != NOBODY_UID)
- memcpy(&new->a_entries[j++],
- &header->a_entries[i],
- sizeof(posix_acl_xattr_entry));
- break;
- case ACL_GROUP:
- if (id != NOBODY_GID)
- memcpy(&new->a_entries[j++],
- &header->a_entries[i],
- sizeof(posix_acl_xattr_entry));
- break;
- default:
- rc = -EIO;
- goto _out;
- }
- }
-
- /* free unused space. */
- rc = lustre_posix_acl_xattr_reduce_space(&new, count, j);
- if (rc >= 0) {
- size = rc;
- *out = new;
- rc = 0;
- }
-
-_out:
- if (rc) {
- kfree(new);
- size = rc;
- }
- return size;
-}
-EXPORT_SYMBOL(lustre_posix_acl_xattr_filter);
-
-/*
- * Release the extended ACL space.
- */
-void lustre_ext_acl_xattr_free(ext_acl_xattr_header *header)
-{
- kfree(header);
-}
-EXPORT_SYMBOL(lustre_ext_acl_xattr_free);
-
-static ext_acl_xattr_entry *
-lustre_ext_acl_xattr_search(ext_acl_xattr_header *header,
- posix_acl_xattr_entry *entry, int *pos)
-{
- int once, start, end, i, j, count = le32_to_cpu(header->a_count);
-
- once = 0;
- start = *pos;
- end = count;
-
-again:
- for (i = start; i < end; i++) {
- if (header->a_entries[i].e_tag == entry->e_tag &&
- header->a_entries[i].e_id == entry->e_id) {
- j = i;
- if (++i >= count)
- i = 0;
- *pos = i;
- return &header->a_entries[j];
- }
- }
-
- if (!once) {
- once = 1;
- start = 0;
- end = *pos;
- goto again;
- }
-
- return NULL;
-}
-
-/*
- * Merge the posix ACL and the extended ACL into new extended ACL.
- */
-ext_acl_xattr_header *
-lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size,
- ext_acl_xattr_header *ext_header)
-{
- int ori_ext_count, posix_count, ext_count, ext_size;
- int i, j, pos = 0, rc = 0;
- posix_acl_xattr_entry pae;
- ext_acl_xattr_header *new;
- ext_acl_xattr_entry *ee, eae;
-
- if (unlikely(size < 0))
- return ERR_PTR(-EINVAL);
- else if (!size)
- posix_count = 0;
- else
- posix_count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
- ori_ext_count = le32_to_cpu(ext_header->a_count);
- ext_count = posix_count + ori_ext_count;
- ext_size = CFS_ACL_XATTR_SIZE(ext_count, ext_acl_xattr);
-
- new = kzalloc(ext_size, GFP_NOFS);
- if (unlikely(!new))
- return ERR_PTR(-ENOMEM);
-
- for (i = 0, j = 0; i < posix_count; i++) {
- lustre_posix_acl_le_to_cpu(&pae, &posix_header->a_entries[i]);
- switch (pae.e_tag) {
- case ACL_USER_OBJ:
- case ACL_GROUP_OBJ:
- case ACL_MASK:
- case ACL_OTHER:
- if (pae.e_id != ACL_UNDEFINED_ID) {
- rc = -EIO;
- goto out;
- }
- case ACL_USER:
- /* ignore "nobody" entry. */
- if (pae.e_id == NOBODY_UID)
- break;
-
- new->a_entries[j].e_tag =
- posix_header->a_entries[i].e_tag;
- new->a_entries[j].e_perm =
- posix_header->a_entries[i].e_perm;
- new->a_entries[j].e_id =
- posix_header->a_entries[i].e_id;
- ee = lustre_ext_acl_xattr_search(ext_header,
- &posix_header->a_entries[i], &pos);
- if (ee) {
- if (posix_header->a_entries[i].e_perm !=
- ee->e_perm)
- /* entry modified. */
- ee->e_stat =
- new->a_entries[j++].e_stat =
- cpu_to_le32(ES_MOD);
- else
- /* entry unchanged. */
- ee->e_stat =
- new->a_entries[j++].e_stat =
- cpu_to_le32(ES_UNC);
- } else {
- /* new entry. */
- new->a_entries[j++].e_stat =
- cpu_to_le32(ES_ADD);
- }
- break;
- case ACL_GROUP:
- /* ignore "nobody" entry. */
- if (pae.e_id == NOBODY_GID)
- break;
- new->a_entries[j].e_tag =
- posix_header->a_entries[i].e_tag;
- new->a_entries[j].e_perm =
- posix_header->a_entries[i].e_perm;
- new->a_entries[j].e_id =
- posix_header->a_entries[i].e_id;
- ee = lustre_ext_acl_xattr_search(ext_header,
- &posix_header->a_entries[i], &pos);
- if (ee) {
- if (posix_header->a_entries[i].e_perm !=
- ee->e_perm)
- /* entry modified. */
- ee->e_stat =
- new->a_entries[j++].e_stat =
- cpu_to_le32(ES_MOD);
- else
- /* entry unchanged. */
- ee->e_stat =
- new->a_entries[j++].e_stat =
- cpu_to_le32(ES_UNC);
- } else {
- /* new entry. */
- new->a_entries[j++].e_stat =
- cpu_to_le32(ES_ADD);
- }
- break;
- default:
- rc = -EIO;
- goto out;
- }
- }
-
- /* process deleted entries. */
- for (i = 0; i < ori_ext_count; i++) {
- lustre_ext_acl_le_to_cpu(&eae, &ext_header->a_entries[i]);
- if (eae.e_stat == ES_UNK) {
- /* ignore "nobody" entry. */
- if ((eae.e_tag == ACL_USER && eae.e_id == NOBODY_UID) ||
- (eae.e_tag == ACL_GROUP && eae.e_id == NOBODY_GID))
- continue;
-
- new->a_entries[j].e_tag =
- ext_header->a_entries[i].e_tag;
- new->a_entries[j].e_perm =
- ext_header->a_entries[i].e_perm;
- new->a_entries[j].e_id = ext_header->a_entries[i].e_id;
- new->a_entries[j++].e_stat = cpu_to_le32(ES_DEL);
- }
- }
-
- new->a_count = cpu_to_le32(j);
- /* free unused space. */
- rc = lustre_ext_acl_xattr_reduce_space(&new, ext_count);
-
-out:
- if (rc) {
- kfree(new);
- new = ERR_PTR(rc);
- }
- return new;
-}
-EXPORT_SYMBOL(lustre_acl_xattr_merge2ext);
-
-#endif
diff --git a/drivers/staging/media/mn88472/Kconfig b/drivers/staging/media/mn88472/Kconfig
deleted file mode 100644
index a85c90a60..000000000
--- a/drivers/staging/media/mn88472/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config DVB_MN88472
- tristate "Panasonic MN88472"
- depends on DVB_CORE && I2C
- select REGMAP_I2C
- default m if !MEDIA_SUBDRV_AUTOSELECT
- help
- Say Y when you want to support this frontend.
diff --git a/drivers/staging/media/mn88472/Makefile b/drivers/staging/media/mn88472/Makefile
deleted file mode 100644
index 5987b7e6d..000000000
--- a/drivers/staging/media/mn88472/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_DVB_MN88472) += mn88472.o
-
-ccflags-y += -Idrivers/media/dvb-core/
-ccflags-y += -Idrivers/media/dvb-frontends/
-ccflags-y += -Idrivers/media/tuners/
diff --git a/drivers/staging/media/mn88472/TODO b/drivers/staging/media/mn88472/TODO
deleted file mode 100644
index b90a14be3..000000000
--- a/drivers/staging/media/mn88472/TODO
+++ /dev/null
@@ -1,21 +0,0 @@
-Driver general quality is not good enough for mainline. Also, other
-device drivers (USB-bridge, tuner) needed for Astrometa receiver in
-question could need some changes. However, if that driver is mainlined
-due to some other device than Astrometa, unrelated TODOs could be
-skipped. In that case rtl28xxu driver needs module parameter to prevent
-driver loading.
-
-Required TODOs:
-* missing lock flags
-* I2C errors
-* tuner sensitivity
-
-*Do not* send any patch fixing checkpatch.pl issues. Currently it passes
-checkpatch.pl tests. I don't want waste my time to review this kind of
-trivial stuff. *Do not* add missing register I/O error checks. Those are
-missing for the reason it is much easier to compare I2C data sniffs when
-there is less lines. Those error checks are about the last thing to be added.
-
-Patches should be submitted to:
-linux-media@vger.kernel.org and Antti Palosaari <crope@iki.fi>
-
diff --git a/drivers/staging/media/mn88472/mn88472.c b/drivers/staging/media/mn88472/mn88472.c
deleted file mode 100644
index c7a76f0fc..000000000
--- a/drivers/staging/media/mn88472/mn88472.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- * Panasonic MN88472 DVB-T/T2/C demodulator driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
- *
- * 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 "mn88472_priv.h"
-
-static int mn88472_get_tune_settings(struct dvb_frontend *fe,
- struct dvb_frontend_tune_settings *s)
-{
- s->min_delay_ms = 800;
- return 0;
-}
-
-static int mn88472_set_frontend(struct dvb_frontend *fe)
-{
- struct i2c_client *client = fe->demodulator_priv;
- struct mn88472_dev *dev = i2c_get_clientdata(client);
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret, i;
- u32 if_frequency = 0;
- u64 tmp;
- u8 delivery_system_val, if_val[3], bw_val[7], bw_val2;
-
- dev_dbg(&client->dev,
- "delivery_system=%d modulation=%d frequency=%d symbol_rate=%d inversion=%d\n",
- c->delivery_system, c->modulation,
- c->frequency, c->symbol_rate, c->inversion);
-
- if (!dev->warm) {
- ret = -EAGAIN;
- goto err;
- }
-
- switch (c->delivery_system) {
- case SYS_DVBT:
- delivery_system_val = 0x02;
- break;
- case SYS_DVBT2:
- delivery_system_val = 0x03;
- break;
- case SYS_DVBC_ANNEX_A:
- delivery_system_val = 0x04;
- break;
- default:
- ret = -EINVAL;
- goto err;
- }
-
- if (c->bandwidth_hz <= 5000000) {
- memcpy(bw_val, "\xe5\x99\x9a\x1b\xa9\x1b\xa9", 7);
- bw_val2 = 0x03;
- } else if (c->bandwidth_hz <= 6000000) {
- /* IF 3570000 Hz, BW 6000000 Hz */
- memcpy(bw_val, "\xbf\x55\x55\x15\x6b\x15\x6b", 7);
- bw_val2 = 0x02;
- } else if (c->bandwidth_hz <= 7000000) {
- /* IF 4570000 Hz, BW 7000000 Hz */
- memcpy(bw_val, "\xa4\x00\x00\x0f\x2c\x0f\x2c", 7);
- bw_val2 = 0x01;
- } else if (c->bandwidth_hz <= 8000000) {
- /* IF 4570000 Hz, BW 8000000 Hz */
- memcpy(bw_val, "\x8f\x80\x00\x08\xee\x08\xee", 7);
- bw_val2 = 0x00;
- } else {
- ret = -EINVAL;
- goto err;
- }
-
- /* program tuner */
- if (fe->ops.tuner_ops.set_params) {
- ret = fe->ops.tuner_ops.set_params(fe);
- if (ret)
- goto err;
- }
-
- if (fe->ops.tuner_ops.get_if_frequency) {
- ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
- if (ret)
- goto err;
-
- dev_dbg(&client->dev, "get_if_frequency=%d\n", if_frequency);
- }
-
- /* Calculate IF registers ( (1<<24)*IF / Xtal ) */
- tmp = div_u64(if_frequency * (u64)(1<<24) + (dev->xtal / 2),
- dev->xtal);
- if_val[0] = (tmp >> 16) & 0xff;
- if_val[1] = (tmp >> 8) & 0xff;
- if_val[2] = (tmp >> 0) & 0xff;
-
- ret = regmap_write(dev->regmap[2], 0xfb, 0x13);
- ret = regmap_write(dev->regmap[2], 0xef, 0x13);
- ret = regmap_write(dev->regmap[2], 0xf9, 0x13);
- if (ret)
- goto err;
-
- ret = regmap_write(dev->regmap[2], 0x00, 0x66);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap[2], 0x01, 0x00);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap[2], 0x02, 0x01);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap[2], 0x03, delivery_system_val);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap[2], 0x04, bw_val2);
- if (ret)
- goto err;
-
- for (i = 0; i < sizeof(if_val); i++) {
- ret = regmap_write(dev->regmap[2], 0x10 + i, if_val[i]);
- if (ret)
- goto err;
- }
-
- for (i = 0; i < sizeof(bw_val); i++) {
- ret = regmap_write(dev->regmap[2], 0x13 + i, bw_val[i]);
- if (ret)
- goto err;
- }
-
- switch (c->delivery_system) {
- case SYS_DVBT:
- ret = regmap_write(dev->regmap[0], 0x07, 0x26);
- ret = regmap_write(dev->regmap[0], 0xb0, 0x0a);
- ret = regmap_write(dev->regmap[0], 0xb4, 0x00);
- ret = regmap_write(dev->regmap[0], 0xcd, 0x1f);
- ret = regmap_write(dev->regmap[0], 0xd4, 0x0a);
- ret = regmap_write(dev->regmap[0], 0xd6, 0x48);
- ret = regmap_write(dev->regmap[0], 0x00, 0xba);
- ret = regmap_write(dev->regmap[0], 0x01, 0x13);
- if (ret)
- goto err;
- break;
- case SYS_DVBT2:
- ret = regmap_write(dev->regmap[2], 0x2b, 0x13);
- ret = regmap_write(dev->regmap[2], 0x4f, 0x05);
- ret = regmap_write(dev->regmap[1], 0xf6, 0x05);
- ret = regmap_write(dev->regmap[0], 0xb0, 0x0a);
- ret = regmap_write(dev->regmap[0], 0xb4, 0xf6);
- ret = regmap_write(dev->regmap[0], 0xcd, 0x01);
- ret = regmap_write(dev->regmap[0], 0xd4, 0x09);
- ret = regmap_write(dev->regmap[0], 0xd6, 0x46);
- ret = regmap_write(dev->regmap[2], 0x30, 0x80);
- ret = regmap_write(dev->regmap[2], 0x32, 0x00);
- if (ret)
- goto err;
- break;
- case SYS_DVBC_ANNEX_A:
- ret = regmap_write(dev->regmap[0], 0xb0, 0x0b);
- ret = regmap_write(dev->regmap[0], 0xb4, 0x00);
- ret = regmap_write(dev->regmap[0], 0xcd, 0x17);
- ret = regmap_write(dev->regmap[0], 0xd4, 0x09);
- ret = regmap_write(dev->regmap[0], 0xd6, 0x48);
- ret = regmap_write(dev->regmap[1], 0x00, 0xb0);
- if (ret)
- goto err;
- break;
- default:
- ret = -EINVAL;
- goto err;
- }
-
- ret = regmap_write(dev->regmap[0], 0x46, 0x00);
- ret = regmap_write(dev->regmap[0], 0xae, 0x00);
-
- switch (dev->ts_mode) {
- case SERIAL_TS_MODE:
- ret = regmap_write(dev->regmap[2], 0x08, 0x1d);
- break;
- case PARALLEL_TS_MODE:
- ret = regmap_write(dev->regmap[2], 0x08, 0x00);
- break;
- default:
- dev_dbg(&client->dev, "ts_mode error: %d\n", dev->ts_mode);
- ret = -EINVAL;
- goto err;
- }
-
- switch (dev->ts_clock) {
- case VARIABLE_TS_CLOCK:
- ret = regmap_write(dev->regmap[0], 0xd9, 0xe3);
- break;
- case FIXED_TS_CLOCK:
- ret = regmap_write(dev->regmap[0], 0xd9, 0xe1);
- break;
- default:
- dev_dbg(&client->dev, "ts_clock error: %d\n", dev->ts_clock);
- ret = -EINVAL;
- goto err;
- }
-
- /* Reset demod */
- ret = regmap_write(dev->regmap[2], 0xf8, 0x9f);
- if (ret)
- goto err;
-
- dev->delivery_system = c->delivery_system;
-
- return 0;
-err:
- dev_dbg(&client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static int mn88472_read_status(struct dvb_frontend *fe, enum fe_status *status)
-{
- struct i2c_client *client = fe->demodulator_priv;
- struct mn88472_dev *dev = i2c_get_clientdata(client);
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret;
- unsigned int utmp;
- int lock = 0;
-
- *status = 0;
-
- if (!dev->warm) {
- ret = -EAGAIN;
- goto err;
- }
-
- switch (c->delivery_system) {
- case SYS_DVBT:
- ret = regmap_read(dev->regmap[0], 0x7F, &utmp);
- if (ret)
- goto err;
- if ((utmp & 0xF) >= 0x09)
- lock = 1;
- break;
- case SYS_DVBT2:
- ret = regmap_read(dev->regmap[2], 0x92, &utmp);
- if (ret)
- goto err;
- if ((utmp & 0xF) >= 0x07)
- *status |= FE_HAS_SIGNAL;
- if ((utmp & 0xF) >= 0x0a)
- *status |= FE_HAS_CARRIER;
- if ((utmp & 0xF) >= 0x0d)
- *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
- break;
- case SYS_DVBC_ANNEX_A:
- ret = regmap_read(dev->regmap[1], 0x84, &utmp);
- if (ret)
- goto err;
- if ((utmp & 0xF) >= 0x08)
- lock = 1;
- break;
- default:
- ret = -EINVAL;
- goto err;
- }
-
- if (lock)
- *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
- FE_HAS_SYNC | FE_HAS_LOCK;
-
- return 0;
-err:
- dev_dbg(&client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static int mn88472_init(struct dvb_frontend *fe)
-{
- struct i2c_client *client = fe->demodulator_priv;
- struct mn88472_dev *dev = i2c_get_clientdata(client);
- int ret, len, remaining;
- const struct firmware *fw = NULL;
- u8 *fw_file = MN88472_FIRMWARE;
- unsigned int tmp;
-
- dev_dbg(&client->dev, "\n");
-
- /* set cold state by default */
- dev->warm = false;
-
- /* power on */
- ret = regmap_write(dev->regmap[2], 0x05, 0x00);
- if (ret)
- goto err;
-
- ret = regmap_bulk_write(dev->regmap[2], 0x0b, "\x00\x00", 2);
- if (ret)
- goto err;
-
- /* check if firmware is already running */
- ret = regmap_read(dev->regmap[0], 0xf5, &tmp);
- if (ret)
- goto err;
-
- if (!(tmp & 0x1)) {
- dev_info(&client->dev, "firmware already running\n");
- dev->warm = true;
- return 0;
- }
-
- /* request the firmware, this will block and timeout */
- ret = reject_firmware(&fw, fw_file, &client->dev);
- if (ret) {
- dev_err(&client->dev, "firmare file '%s' not found\n",
- fw_file);
- goto err;
- }
-
- dev_info(&client->dev, "downloading firmware from file '%s'\n",
- fw_file);
-
- ret = regmap_write(dev->regmap[0], 0xf5, 0x03);
- if (ret)
- goto firmware_release;
-
- for (remaining = fw->size; remaining > 0;
- remaining -= (dev->i2c_wr_max - 1)) {
- len = remaining;
- if (len > (dev->i2c_wr_max - 1))
- len = dev->i2c_wr_max - 1;
-
- ret = regmap_bulk_write(dev->regmap[0], 0xf6,
- &fw->data[fw->size - remaining], len);
- if (ret) {
- dev_err(&client->dev,
- "firmware download failed=%d\n", ret);
- goto firmware_release;
- }
- }
-
- /* parity check of firmware */
- ret = regmap_read(dev->regmap[0], 0xf8, &tmp);
- if (ret) {
- dev_err(&client->dev,
- "parity reg read failed=%d\n", ret);
- goto firmware_release;
- }
- if (tmp & 0x10) {
- dev_err(&client->dev,
- "firmware parity check failed=0x%x\n", tmp);
- goto firmware_release;
- }
- dev_err(&client->dev, "firmware parity check succeeded=0x%x\n", tmp);
-
- ret = regmap_write(dev->regmap[0], 0xf5, 0x00);
- if (ret)
- goto firmware_release;
-
- release_firmware(fw);
- fw = NULL;
-
- /* warm state */
- dev->warm = true;
-
- return 0;
-firmware_release:
- release_firmware(fw);
-err:
- dev_dbg(&client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static int mn88472_sleep(struct dvb_frontend *fe)
-{
- struct i2c_client *client = fe->demodulator_priv;
- struct mn88472_dev *dev = i2c_get_clientdata(client);
- int ret;
-
- dev_dbg(&client->dev, "\n");
-
- /* power off */
- ret = regmap_write(dev->regmap[2], 0x0b, 0x30);
-
- if (ret)
- goto err;
-
- ret = regmap_write(dev->regmap[2], 0x05, 0x3e);
- if (ret)
- goto err;
-
- dev->delivery_system = SYS_UNDEFINED;
-
- return 0;
-err:
- dev_dbg(&client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static struct dvb_frontend_ops mn88472_ops = {
- .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
- .info = {
- .name = "Panasonic MN88472",
- .symbol_rate_min = 1000000,
- .symbol_rate_max = 7200000,
- .caps = FE_CAN_FEC_1_2 |
- FE_CAN_FEC_2_3 |
- FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 |
- FE_CAN_FEC_7_8 |
- FE_CAN_FEC_AUTO |
- FE_CAN_QPSK |
- FE_CAN_QAM_16 |
- FE_CAN_QAM_32 |
- FE_CAN_QAM_64 |
- FE_CAN_QAM_128 |
- FE_CAN_QAM_256 |
- FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO |
- FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO |
- FE_CAN_MUTE_TS |
- FE_CAN_2G_MODULATION |
- FE_CAN_MULTISTREAM
- },
-
- .get_tune_settings = mn88472_get_tune_settings,
-
- .init = mn88472_init,
- .sleep = mn88472_sleep,
-
- .set_frontend = mn88472_set_frontend,
-
- .read_status = mn88472_read_status,
-};
-
-static int mn88472_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct mn88472_config *config = client->dev.platform_data;
- struct mn88472_dev *dev;
- int ret;
- unsigned int utmp;
- static const struct regmap_config regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- };
-
- dev_dbg(&client->dev, "\n");
-
- /* Caller really need to provide pointer for frontend we create. */
- if (config->fe == NULL) {
- dev_err(&client->dev, "frontend pointer not defined\n");
- ret = -EINVAL;
- goto err;
- }
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) {
- ret = -ENOMEM;
- goto err;
- }
-
- dev->i2c_wr_max = config->i2c_wr_max;
- dev->xtal = config->xtal;
- dev->ts_mode = config->ts_mode;
- dev->ts_clock = config->ts_clock;
- dev->client[0] = client;
- dev->regmap[0] = regmap_init_i2c(dev->client[0], &regmap_config);
- if (IS_ERR(dev->regmap[0])) {
- ret = PTR_ERR(dev->regmap[0]);
- goto err_kfree;
- }
-
- /* check demod answers to I2C */
- ret = regmap_read(dev->regmap[0], 0x00, &utmp);
- if (ret)
- goto err_regmap_0_regmap_exit;
-
- /*
- * Chip has three I2C addresses for different register pages. Used
- * addresses are 0x18, 0x1a and 0x1c. We register two dummy clients,
- * 0x1a and 0x1c, in order to get own I2C client for each register page.
- */
- dev->client[1] = i2c_new_dummy(client->adapter, 0x1a);
- if (!dev->client[1]) {
- ret = -ENODEV;
- dev_err(&client->dev, "I2C registration failed\n");
- if (ret)
- goto err_regmap_0_regmap_exit;
- }
- dev->regmap[1] = regmap_init_i2c(dev->client[1], &regmap_config);
- if (IS_ERR(dev->regmap[1])) {
- ret = PTR_ERR(dev->regmap[1]);
- goto err_client_1_i2c_unregister_device;
- }
- i2c_set_clientdata(dev->client[1], dev);
-
- dev->client[2] = i2c_new_dummy(client->adapter, 0x1c);
- if (!dev->client[2]) {
- ret = -ENODEV;
- dev_err(&client->dev, "2nd I2C registration failed\n");
- if (ret)
- goto err_regmap_1_regmap_exit;
- }
- dev->regmap[2] = regmap_init_i2c(dev->client[2], &regmap_config);
- if (IS_ERR(dev->regmap[2])) {
- ret = PTR_ERR(dev->regmap[2]);
- goto err_client_2_i2c_unregister_device;
- }
- i2c_set_clientdata(dev->client[2], dev);
-
- /* create dvb_frontend */
- memcpy(&dev->fe.ops, &mn88472_ops, sizeof(struct dvb_frontend_ops));
- dev->fe.demodulator_priv = client;
- *config->fe = &dev->fe;
- i2c_set_clientdata(client, dev);
-
- dev_info(&client->dev, "Panasonic MN88472 successfully attached\n");
- return 0;
-
-err_client_2_i2c_unregister_device:
- i2c_unregister_device(dev->client[2]);
-err_regmap_1_regmap_exit:
- regmap_exit(dev->regmap[1]);
-err_client_1_i2c_unregister_device:
- i2c_unregister_device(dev->client[1]);
-err_regmap_0_regmap_exit:
- regmap_exit(dev->regmap[0]);
-err_kfree:
- kfree(dev);
-err:
- dev_dbg(&client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static int mn88472_remove(struct i2c_client *client)
-{
- struct mn88472_dev *dev = i2c_get_clientdata(client);
-
- dev_dbg(&client->dev, "\n");
-
- regmap_exit(dev->regmap[2]);
- i2c_unregister_device(dev->client[2]);
-
- regmap_exit(dev->regmap[1]);
- i2c_unregister_device(dev->client[1]);
-
- regmap_exit(dev->regmap[0]);
-
- kfree(dev);
-
- return 0;
-}
-
-static const struct i2c_device_id mn88472_id_table[] = {
- {"mn88472", 0},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, mn88472_id_table);
-
-static struct i2c_driver mn88472_driver = {
- .driver = {
- .name = "mn88472",
- },
- .probe = mn88472_probe,
- .remove = mn88472_remove,
- .id_table = mn88472_id_table,
-};
-
-module_i2c_driver(mn88472_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Panasonic MN88472 DVB-T/T2/C demodulator driver");
-MODULE_LICENSE("GPL");
-/*(DEBLOBBED)*/
diff --git a/drivers/staging/media/mn88472/mn88472_priv.h b/drivers/staging/media/mn88472/mn88472_priv.h
deleted file mode 100644
index da6531d1e..000000000
--- a/drivers/staging/media/mn88472/mn88472_priv.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Panasonic MN88472 DVB-T/T2/C demodulator driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
- *
- * 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.
- */
-
-#ifndef MN88472_PRIV_H
-#define MN88472_PRIV_H
-
-#include "dvb_frontend.h"
-#include "mn88472.h"
-#include <linux/firmware.h>
-#include <linux/regmap.h>
-
-#define MN88472_FIRMWARE "/*(DEBLOBBED)*/"
-
-struct mn88472_dev {
- struct i2c_client *client[3];
- struct regmap *regmap[3];
- struct dvb_frontend fe;
- u16 i2c_wr_max;
- enum fe_delivery_system delivery_system;
- bool warm; /* FW running */
- u32 xtal;
- int ts_mode;
- int ts_clock;
-};
-
-#endif
diff --git a/drivers/staging/media/mx2/Kconfig b/drivers/staging/media/mx2/Kconfig
deleted file mode 100644
index beaa885cf..000000000
--- a/drivers/staging/media/mx2/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-config VIDEO_MX2
- tristate "i.MX27 Camera Sensor Interface driver"
- depends on VIDEO_DEV && SOC_CAMERA
- depends on SOC_IMX27 || COMPILE_TEST
- depends on HAS_DMA
- select VIDEOBUF2_DMA_CONTIG
- ---help---
- This is a v4l2 driver for the i.MX27 Camera Sensor Interface
-
- This driver is deprecated: it should become a stand-alone driver
- instead of using the soc-camera framework.
-
- Unless someone is willing to take this on (unlikely with such
- ancient hardware) it is going to be removed from the kernel
- soon.
diff --git a/drivers/staging/media/mx2/Makefile b/drivers/staging/media/mx2/Makefile
deleted file mode 100644
index fc5b2826a..000000000
--- a/drivers/staging/media/mx2/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# Makefile for i.MX27 Camera Sensor driver
-
-obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o
diff --git a/drivers/staging/media/mx2/TODO b/drivers/staging/media/mx2/TODO
deleted file mode 100644
index bc68fa443..000000000
--- a/drivers/staging/media/mx2/TODO
+++ /dev/null
@@ -1,10 +0,0 @@
-This driver is deprecated: it should become a stand-alone driver instead of
-using the soc-camera framework.
-
-Unless someone is willing to take this on (unlikely with such ancient
-hardware) it is going to be removed from the kernel soon.
-
-Note that trivial patches will not be accepted anymore, only a full conversion.
-
-If you want to convert this driver, please contact the linux-media mailinglist
-(see http://linuxtv.org/lists.php).
diff --git a/drivers/staging/media/mx2/mx2_camera.c b/drivers/staging/media/mx2/mx2_camera.c
deleted file mode 100644
index 48dd5b785..000000000
--- a/drivers/staging/media/mx2/mx2_camera.c
+++ /dev/null
@@ -1,1636 +0,0 @@
-/*
- * V4L2 Driver for i.MX27 camera host
- *
- * Copyright (C) 2008, Sascha Hauer, Pengutronix
- * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography
- * Copyright (C) 2012, Javier Martin, Vista Silicon S.L.
- *
- * 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.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/gcd.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/math64.h>
-#include <linux/mm.h>
-#include <linux/moduleparam.h>
-#include <linux/time.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-dev.h>
-#include <media/videobuf2-v4l2.h>
-#include <media/videobuf2-dma-contig.h>
-#include <media/soc_camera.h>
-#include <media/drv-intf/soc_mediabus.h>
-
-#include <linux/videodev2.h>
-
-#include <linux/platform_data/media/camera-mx2.h>
-
-#include <asm/dma.h>
-
-#define MX2_CAM_DRV_NAME "mx2-camera"
-#define MX2_CAM_VERSION "0.0.6"
-#define MX2_CAM_DRIVER_DESCRIPTION "i.MX2x_Camera"
-
-/* reset values */
-#define CSICR1_RESET_VAL 0x40000800
-#define CSICR2_RESET_VAL 0x0
-#define CSICR3_RESET_VAL 0x0
-
-/* csi control reg 1 */
-#define CSICR1_SWAP16_EN (1 << 31)
-#define CSICR1_EXT_VSYNC (1 << 30)
-#define CSICR1_EOF_INTEN (1 << 29)
-#define CSICR1_PRP_IF_EN (1 << 28)
-#define CSICR1_CCIR_MODE (1 << 27)
-#define CSICR1_COF_INTEN (1 << 26)
-#define CSICR1_SF_OR_INTEN (1 << 25)
-#define CSICR1_RF_OR_INTEN (1 << 24)
-#define CSICR1_STATFF_LEVEL (3 << 22)
-#define CSICR1_STATFF_INTEN (1 << 21)
-#define CSICR1_RXFF_LEVEL(l) (((l) & 3) << 19)
-#define CSICR1_RXFF_INTEN (1 << 18)
-#define CSICR1_SOF_POL (1 << 17)
-#define CSICR1_SOF_INTEN (1 << 16)
-#define CSICR1_MCLKDIV(d) (((d) & 0xF) << 12)
-#define CSICR1_HSYNC_POL (1 << 11)
-#define CSICR1_CCIR_EN (1 << 10)
-#define CSICR1_MCLKEN (1 << 9)
-#define CSICR1_FCC (1 << 8)
-#define CSICR1_PACK_DIR (1 << 7)
-#define CSICR1_CLR_STATFIFO (1 << 6)
-#define CSICR1_CLR_RXFIFO (1 << 5)
-#define CSICR1_GCLK_MODE (1 << 4)
-#define CSICR1_INV_DATA (1 << 3)
-#define CSICR1_INV_PCLK (1 << 2)
-#define CSICR1_REDGE (1 << 1)
-#define CSICR1_FMT_MASK (CSICR1_PACK_DIR | CSICR1_SWAP16_EN)
-
-#define SHIFT_STATFF_LEVEL 22
-#define SHIFT_RXFF_LEVEL 19
-#define SHIFT_MCLKDIV 12
-
-#define SHIFT_FRMCNT 16
-
-#define CSICR1 0x00
-#define CSICR2 0x04
-#define CSISR 0x08
-#define CSISTATFIFO 0x0c
-#define CSIRFIFO 0x10
-#define CSIRXCNT 0x14
-#define CSICR3 0x1c
-#define CSIDMASA_STATFIFO 0x20
-#define CSIDMATA_STATFIFO 0x24
-#define CSIDMASA_FB1 0x28
-#define CSIDMASA_FB2 0x2c
-#define CSIFBUF_PARA 0x30
-#define CSIIMAG_PARA 0x34
-
-/* EMMA PrP */
-#define PRP_CNTL 0x00
-#define PRP_INTR_CNTL 0x04
-#define PRP_INTRSTATUS 0x08
-#define PRP_SOURCE_Y_PTR 0x0c
-#define PRP_SOURCE_CB_PTR 0x10
-#define PRP_SOURCE_CR_PTR 0x14
-#define PRP_DEST_RGB1_PTR 0x18
-#define PRP_DEST_RGB2_PTR 0x1c
-#define PRP_DEST_Y_PTR 0x20
-#define PRP_DEST_CB_PTR 0x24
-#define PRP_DEST_CR_PTR 0x28
-#define PRP_SRC_FRAME_SIZE 0x2c
-#define PRP_DEST_CH1_LINE_STRIDE 0x30
-#define PRP_SRC_PIXEL_FORMAT_CNTL 0x34
-#define PRP_CH1_PIXEL_FORMAT_CNTL 0x38
-#define PRP_CH1_OUT_IMAGE_SIZE 0x3c
-#define PRP_CH2_OUT_IMAGE_SIZE 0x40
-#define PRP_SRC_LINE_STRIDE 0x44
-#define PRP_CSC_COEF_012 0x48
-#define PRP_CSC_COEF_345 0x4c
-#define PRP_CSC_COEF_678 0x50
-#define PRP_CH1_RZ_HORI_COEF1 0x54
-#define PRP_CH1_RZ_HORI_COEF2 0x58
-#define PRP_CH1_RZ_HORI_VALID 0x5c
-#define PRP_CH1_RZ_VERT_COEF1 0x60
-#define PRP_CH1_RZ_VERT_COEF2 0x64
-#define PRP_CH1_RZ_VERT_VALID 0x68
-#define PRP_CH2_RZ_HORI_COEF1 0x6c
-#define PRP_CH2_RZ_HORI_COEF2 0x70
-#define PRP_CH2_RZ_HORI_VALID 0x74
-#define PRP_CH2_RZ_VERT_COEF1 0x78
-#define PRP_CH2_RZ_VERT_COEF2 0x7c
-#define PRP_CH2_RZ_VERT_VALID 0x80
-
-#define PRP_CNTL_CH1EN (1 << 0)
-#define PRP_CNTL_CH2EN (1 << 1)
-#define PRP_CNTL_CSIEN (1 << 2)
-#define PRP_CNTL_DATA_IN_YUV420 (0 << 3)
-#define PRP_CNTL_DATA_IN_YUV422 (1 << 3)
-#define PRP_CNTL_DATA_IN_RGB16 (2 << 3)
-#define PRP_CNTL_DATA_IN_RGB32 (3 << 3)
-#define PRP_CNTL_CH1_OUT_RGB8 (0 << 5)
-#define PRP_CNTL_CH1_OUT_RGB16 (1 << 5)
-#define PRP_CNTL_CH1_OUT_RGB32 (2 << 5)
-#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5)
-#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7)
-#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7)
-#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7)
-#define PRP_CNTL_CH1_LEN (1 << 9)
-#define PRP_CNTL_CH2_LEN (1 << 10)
-#define PRP_CNTL_SKIP_FRAME (1 << 11)
-#define PRP_CNTL_SWRST (1 << 12)
-#define PRP_CNTL_CLKEN (1 << 13)
-#define PRP_CNTL_WEN (1 << 14)
-#define PRP_CNTL_CH1BYP (1 << 15)
-#define PRP_CNTL_IN_TSKIP(x) ((x) << 16)
-#define PRP_CNTL_CH1_TSKIP(x) ((x) << 19)
-#define PRP_CNTL_CH2_TSKIP(x) ((x) << 22)
-#define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25)
-#define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27)
-#define PRP_CNTL_CH2B1EN (1 << 29)
-#define PRP_CNTL_CH2B2EN (1 << 30)
-#define PRP_CNTL_CH2FEN (1 << 31)
-
-/* IRQ Enable and status register */
-#define PRP_INTR_RDERR (1 << 0)
-#define PRP_INTR_CH1WERR (1 << 1)
-#define PRP_INTR_CH2WERR (1 << 2)
-#define PRP_INTR_CH1FC (1 << 3)
-#define PRP_INTR_CH2FC (1 << 5)
-#define PRP_INTR_LBOVF (1 << 7)
-#define PRP_INTR_CH2OVF (1 << 8)
-
-/* Resizing registers */
-#define PRP_RZ_VALID_TBL_LEN(x) ((x) << 24)
-#define PRP_RZ_VALID_BILINEAR (1 << 31)
-
-#define MAX_VIDEO_MEM 16
-
-#define RESIZE_NUM_MIN 1
-#define RESIZE_NUM_MAX 20
-#define BC_COEF 3
-#define SZ_COEF (1 << BC_COEF)
-
-#define RESIZE_DIR_H 0
-#define RESIZE_DIR_V 1
-
-#define RESIZE_ALGO_BILINEAR 0
-#define RESIZE_ALGO_AVERAGING 1
-
-struct mx2_prp_cfg {
- int channel;
- u32 in_fmt;
- u32 out_fmt;
- u32 src_pixel;
- u32 ch1_pixel;
- u32 irq_flags;
- u32 csicr1;
-};
-
-/* prp resizing parameters */
-struct emma_prp_resize {
- int algo; /* type of algorithm used */
- int len; /* number of coefficients */
- unsigned char s[RESIZE_NUM_MAX]; /* table of coefficients */
-};
-
-/* prp configuration for a client-host fmt pair */
-struct mx2_fmt_cfg {
- u32 in_fmt;
- u32 out_fmt;
- struct mx2_prp_cfg cfg;
-};
-
-struct mx2_buf_internal {
- struct list_head queue;
- int bufnum;
- bool discard;
-};
-
-/* buffer for one video frame */
-struct mx2_buffer {
- /* common v4l buffer stuff -- must be first */
- struct vb2_v4l2_buffer vb;
- struct mx2_buf_internal internal;
-};
-
-enum mx2_camera_type {
- IMX27_CAMERA,
-};
-
-struct mx2_camera_dev {
- struct device *dev;
- struct soc_camera_host soc_host;
- struct clk *clk_emma_ahb, *clk_emma_ipg;
- struct clk *clk_csi_ahb, *clk_csi_per;
-
- void __iomem *base_csi, *base_emma;
-
- struct mx2_camera_platform_data *pdata;
- unsigned long platform_flags;
-
- struct list_head capture;
- struct list_head active_bufs;
- struct list_head discard;
-
- spinlock_t lock;
-
- int dma;
- struct mx2_buffer *active;
- struct mx2_buffer *fb1_active;
- struct mx2_buffer *fb2_active;
-
- u32 csicr1;
- enum mx2_camera_type devtype;
-
- struct mx2_buf_internal buf_discard[2];
- void *discard_buffer;
- dma_addr_t discard_buffer_dma;
- size_t discard_size;
- struct mx2_fmt_cfg *emma_prp;
- struct emma_prp_resize resizing[2];
- unsigned int s_width, s_height;
- u32 frame_count;
- struct vb2_alloc_ctx *alloc_ctx;
-};
-
-static struct platform_device_id mx2_camera_devtype[] = {
- {
- .name = "imx27-camera",
- .driver_data = IMX27_CAMERA,
- }, {
- /* sentinel */
- }
-};
-MODULE_DEVICE_TABLE(platform, mx2_camera_devtype);
-
-static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf)
-{
- return container_of(int_buf, struct mx2_buffer, internal);
-}
-
-static struct mx2_fmt_cfg mx27_emma_prp_table[] = {
- /*
- * This is a generic configuration which is valid for most
- * prp input-output format combinations.
- * We set the incoming and outgoing pixelformat to a
- * 16 Bit wide format and adjust the bytesperline
- * accordingly. With this configuration the inputdata
- * will not be changed by the emma and could be any type
- * of 16 Bit Pixelformat.
- */
- {
- .in_fmt = 0,
- .out_fmt = 0,
- .cfg = {
- .channel = 1,
- .in_fmt = PRP_CNTL_DATA_IN_RGB16,
- .out_fmt = PRP_CNTL_CH1_OUT_RGB16,
- .src_pixel = 0x2ca00565, /* RGB565 */
- .ch1_pixel = 0x2ca00565, /* RGB565 */
- .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR |
- PRP_INTR_CH1FC | PRP_INTR_LBOVF,
- .csicr1 = 0,
- }
- },
- {
- .in_fmt = MEDIA_BUS_FMT_UYVY8_2X8,
- .out_fmt = V4L2_PIX_FMT_YUYV,
- .cfg = {
- .channel = 1,
- .in_fmt = PRP_CNTL_DATA_IN_YUV422,
- .out_fmt = PRP_CNTL_CH1_OUT_YUV422,
- .src_pixel = 0x22000888, /* YUV422 (YUYV) */
- .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */
- .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR |
- PRP_INTR_CH1FC | PRP_INTR_LBOVF,
- .csicr1 = CSICR1_SWAP16_EN,
- }
- },
- {
- .in_fmt = MEDIA_BUS_FMT_YUYV8_2X8,
- .out_fmt = V4L2_PIX_FMT_YUYV,
- .cfg = {
- .channel = 1,
- .in_fmt = PRP_CNTL_DATA_IN_YUV422,
- .out_fmt = PRP_CNTL_CH1_OUT_YUV422,
- .src_pixel = 0x22000888, /* YUV422 (YUYV) */
- .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */
- .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR |
- PRP_INTR_CH1FC | PRP_INTR_LBOVF,
- .csicr1 = CSICR1_PACK_DIR,
- }
- },
- {
- .in_fmt = MEDIA_BUS_FMT_YUYV8_2X8,
- .out_fmt = V4L2_PIX_FMT_YUV420,
- .cfg = {
- .channel = 2,
- .in_fmt = PRP_CNTL_DATA_IN_YUV422,
- .out_fmt = PRP_CNTL_CH2_OUT_YUV420,
- .src_pixel = 0x22000888, /* YUV422 (YUYV) */
- .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR |
- PRP_INTR_CH2FC | PRP_INTR_LBOVF |
- PRP_INTR_CH2OVF,
- .csicr1 = CSICR1_PACK_DIR,
- }
- },
- {
- .in_fmt = MEDIA_BUS_FMT_UYVY8_2X8,
- .out_fmt = V4L2_PIX_FMT_YUV420,
- .cfg = {
- .channel = 2,
- .in_fmt = PRP_CNTL_DATA_IN_YUV422,
- .out_fmt = PRP_CNTL_CH2_OUT_YUV420,
- .src_pixel = 0x22000888, /* YUV422 (YUYV) */
- .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR |
- PRP_INTR_CH2FC | PRP_INTR_LBOVF |
- PRP_INTR_CH2OVF,
- .csicr1 = CSICR1_SWAP16_EN,
- }
- },
-};
-
-static struct mx2_fmt_cfg *mx27_emma_prp_get_format(u32 in_fmt, u32 out_fmt)
-{
- int i;
-
- for (i = 1; i < ARRAY_SIZE(mx27_emma_prp_table); i++)
- if ((mx27_emma_prp_table[i].in_fmt == in_fmt) &&
- (mx27_emma_prp_table[i].out_fmt == out_fmt)) {
- return &mx27_emma_prp_table[i];
- }
- /* If no match return the most generic configuration */
- return &mx27_emma_prp_table[0];
-};
-
-static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev,
- unsigned long phys, int bufnum)
-{
- struct mx2_fmt_cfg *prp = pcdev->emma_prp;
-
- if (prp->cfg.channel == 1) {
- writel(phys, pcdev->base_emma +
- PRP_DEST_RGB1_PTR + 4 * bufnum);
- } else {
- writel(phys, pcdev->base_emma +
- PRP_DEST_Y_PTR - 0x14 * bufnum);
- if (prp->out_fmt == V4L2_PIX_FMT_YUV420) {
- u32 imgsize = pcdev->soc_host.icd->user_height *
- pcdev->soc_host.icd->user_width;
-
- writel(phys + imgsize, pcdev->base_emma +
- PRP_DEST_CB_PTR - 0x14 * bufnum);
- writel(phys + ((5 * imgsize) / 4), pcdev->base_emma +
- PRP_DEST_CR_PTR - 0x14 * bufnum);
- }
- }
-}
-
-static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
-{
- clk_disable_unprepare(pcdev->clk_csi_ahb);
- clk_disable_unprepare(pcdev->clk_csi_per);
- writel(0, pcdev->base_csi + CSICR1);
- writel(0, pcdev->base_emma + PRP_CNTL);
-}
-
-static int mx2_camera_add_device(struct soc_camera_device *icd)
-{
- dev_info(icd->parent, "Camera driver attached to camera %d\n",
- icd->devnum);
-
- return 0;
-}
-
-static void mx2_camera_remove_device(struct soc_camera_device *icd)
-{
- dev_info(icd->parent, "Camera driver detached from camera %d\n",
- icd->devnum);
-}
-
-/*
- * The following two functions absolutely depend on the fact, that
- * there can be only one camera on mx2 camera sensor interface
- */
-static int mx2_camera_clock_start(struct soc_camera_host *ici)
-{
- struct mx2_camera_dev *pcdev = ici->priv;
- int ret;
- u32 csicr1;
-
- ret = clk_prepare_enable(pcdev->clk_csi_ahb);
- if (ret < 0)
- return ret;
-
- ret = clk_prepare_enable(pcdev->clk_csi_per);
- if (ret < 0)
- goto exit_csi_ahb;
-
- csicr1 = CSICR1_MCLKEN | CSICR1_PRP_IF_EN | CSICR1_FCC |
- CSICR1_RXFF_LEVEL(0);
-
- pcdev->csicr1 = csicr1;
- writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
-
- pcdev->frame_count = 0;
-
- return 0;
-
-exit_csi_ahb:
- clk_disable_unprepare(pcdev->clk_csi_ahb);
-
- return ret;
-}
-
-static void mx2_camera_clock_stop(struct soc_camera_host *ici)
-{
- struct mx2_camera_dev *pcdev = ici->priv;
-
- mx2_camera_deactivate(pcdev);
-}
-
-/*
- * Videobuf operations
- */
-static int mx2_videobuf_setup(struct vb2_queue *vq,
- unsigned int *count, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
-{
- struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx2_camera_dev *pcdev = ici->priv;
-
- dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]);
-
- alloc_ctxs[0] = pcdev->alloc_ctx;
-
- sizes[0] = icd->sizeimage;
-
- if (0 == *count)
- *count = 32;
- if (!*num_planes &&
- sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024)
- *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0];
-
- *num_planes = 1;
-
- return 0;
-}
-
-static int mx2_videobuf_prepare(struct vb2_buffer *vb)
-{
- struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
- int ret = 0;
-
- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
- vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
-
-#ifdef DEBUG
- /*
- * This can be useful if you want to see if we actually fill
- * the buffer with something
- */
- memset((void *)vb2_plane_vaddr(vb, 0),
- 0xaa, vb2_get_plane_payload(vb, 0));
-#endif
-
- vb2_set_plane_payload(vb, 0, icd->sizeimage);
- if (vb2_plane_vaddr(vb, 0) &&
- vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
- ret = -EINVAL;
- goto out;
- }
-
- return 0;
-
-out:
- return ret;
-}
-
-static void mx2_videobuf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
- struct soc_camera_host *ici =
- to_soc_camera_host(icd->parent);
- struct mx2_camera_dev *pcdev = ici->priv;
- struct mx2_buffer *buf = container_of(vbuf, struct mx2_buffer, vb);
- unsigned long flags;
-
- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
- vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
-
- spin_lock_irqsave(&pcdev->lock, flags);
-
- list_add_tail(&buf->internal.queue, &pcdev->capture);
-
- spin_unlock_irqrestore(&pcdev->lock, flags);
-}
-
-static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
- int bytesperline)
-{
- struct soc_camera_host *ici =
- to_soc_camera_host(icd->parent);
- struct mx2_camera_dev *pcdev = ici->priv;
- struct mx2_fmt_cfg *prp = pcdev->emma_prp;
-
- writel((pcdev->s_width << 16) | pcdev->s_height,
- pcdev->base_emma + PRP_SRC_FRAME_SIZE);
- writel(prp->cfg.src_pixel,
- pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
- if (prp->cfg.channel == 1) {
- writel((icd->user_width << 16) | icd->user_height,
- pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE);
- writel(bytesperline,
- pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE);
- writel(prp->cfg.ch1_pixel,
- pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL);
- } else { /* channel 2 */
- writel((icd->user_width << 16) | icd->user_height,
- pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
- }
-
- /* Enable interrupts */
- writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL);
-}
-
-static void mx2_prp_resize_commit(struct mx2_camera_dev *pcdev)
-{
- int dir;
-
- for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) {
- unsigned char *s = pcdev->resizing[dir].s;
- int len = pcdev->resizing[dir].len;
- unsigned int coeff[2] = {0, 0};
- unsigned int valid = 0;
- int i;
-
- if (len == 0)
- continue;
-
- for (i = RESIZE_NUM_MAX - 1; i >= 0; i--) {
- int j;
-
- j = i > 9 ? 1 : 0;
- coeff[j] = (coeff[j] << BC_COEF) |
- (s[i] & (SZ_COEF - 1));
-
- if (i == 5 || i == 15)
- coeff[j] <<= 1;
-
- valid = (valid << 1) | (s[i] >> BC_COEF);
- }
-
- valid |= PRP_RZ_VALID_TBL_LEN(len);
-
- if (pcdev->resizing[dir].algo == RESIZE_ALGO_BILINEAR)
- valid |= PRP_RZ_VALID_BILINEAR;
-
- if (pcdev->emma_prp->cfg.channel == 1) {
- if (dir == RESIZE_DIR_H) {
- writel(coeff[0], pcdev->base_emma +
- PRP_CH1_RZ_HORI_COEF1);
- writel(coeff[1], pcdev->base_emma +
- PRP_CH1_RZ_HORI_COEF2);
- writel(valid, pcdev->base_emma +
- PRP_CH1_RZ_HORI_VALID);
- } else {
- writel(coeff[0], pcdev->base_emma +
- PRP_CH1_RZ_VERT_COEF1);
- writel(coeff[1], pcdev->base_emma +
- PRP_CH1_RZ_VERT_COEF2);
- writel(valid, pcdev->base_emma +
- PRP_CH1_RZ_VERT_VALID);
- }
- } else {
- if (dir == RESIZE_DIR_H) {
- writel(coeff[0], pcdev->base_emma +
- PRP_CH2_RZ_HORI_COEF1);
- writel(coeff[1], pcdev->base_emma +
- PRP_CH2_RZ_HORI_COEF2);
- writel(valid, pcdev->base_emma +
- PRP_CH2_RZ_HORI_VALID);
- } else {
- writel(coeff[0], pcdev->base_emma +
- PRP_CH2_RZ_VERT_COEF1);
- writel(coeff[1], pcdev->base_emma +
- PRP_CH2_RZ_VERT_COEF2);
- writel(valid, pcdev->base_emma +
- PRP_CH2_RZ_VERT_VALID);
- }
- }
- }
-}
-
-static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
-{
- struct soc_camera_device *icd = soc_camera_from_vb2q(q);
- struct soc_camera_host *ici =
- to_soc_camera_host(icd->parent);
- struct mx2_camera_dev *pcdev = ici->priv;
- struct mx2_fmt_cfg *prp = pcdev->emma_prp;
- struct vb2_buffer *vb;
- struct mx2_buffer *buf;
- unsigned long phys;
- int bytesperline;
- unsigned long flags;
-
- if (count < 2)
- return -ENOBUFS;
-
- spin_lock_irqsave(&pcdev->lock, flags);
-
- buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
- internal.queue);
- buf->internal.bufnum = 0;
- vb = &buf->vb.vb2_buf;
-
- phys = vb2_dma_contig_plane_dma_addr(vb, 0);
- mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum);
- list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
-
- buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
- internal.queue);
- buf->internal.bufnum = 1;
- vb = &buf->vb.vb2_buf;
-
- phys = vb2_dma_contig_plane_dma_addr(vb, 0);
- mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum);
- list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
-
- bytesperline = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
- if (bytesperline < 0) {
- spin_unlock_irqrestore(&pcdev->lock, flags);
- return bytesperline;
- }
-
- /*
- * I didn't manage to properly enable/disable the prp
- * on a per frame basis during running transfers,
- * thus we allocate a buffer here and use it to
- * discard frames when no buffer is available.
- * Feel free to work on this ;)
- */
- pcdev->discard_size = icd->user_height * bytesperline;
- pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
- pcdev->discard_size,
- &pcdev->discard_buffer_dma, GFP_ATOMIC);
- if (!pcdev->discard_buffer) {
- spin_unlock_irqrestore(&pcdev->lock, flags);
- return -ENOMEM;
- }
-
- pcdev->buf_discard[0].discard = true;
- list_add_tail(&pcdev->buf_discard[0].queue,
- &pcdev->discard);
-
- pcdev->buf_discard[1].discard = true;
- list_add_tail(&pcdev->buf_discard[1].queue,
- &pcdev->discard);
-
- mx2_prp_resize_commit(pcdev);
-
- mx27_camera_emma_buf_init(icd, bytesperline);
-
- if (prp->cfg.channel == 1) {
- writel(PRP_CNTL_CH1EN |
- PRP_CNTL_CSIEN |
- prp->cfg.in_fmt |
- prp->cfg.out_fmt |
- PRP_CNTL_CH1_LEN |
- PRP_CNTL_CH1BYP |
- PRP_CNTL_CH1_TSKIP(0) |
- PRP_CNTL_IN_TSKIP(0),
- pcdev->base_emma + PRP_CNTL);
- } else {
- writel(PRP_CNTL_CH2EN |
- PRP_CNTL_CSIEN |
- prp->cfg.in_fmt |
- prp->cfg.out_fmt |
- PRP_CNTL_CH2_LEN |
- PRP_CNTL_CH2_TSKIP(0) |
- PRP_CNTL_IN_TSKIP(0),
- pcdev->base_emma + PRP_CNTL);
- }
- spin_unlock_irqrestore(&pcdev->lock, flags);
-
- return 0;
-}
-
-static void mx2_stop_streaming(struct vb2_queue *q)
-{
- struct soc_camera_device *icd = soc_camera_from_vb2q(q);
- struct soc_camera_host *ici =
- to_soc_camera_host(icd->parent);
- struct mx2_camera_dev *pcdev = ici->priv;
- struct mx2_fmt_cfg *prp = pcdev->emma_prp;
- unsigned long flags;
- void *b;
- u32 cntl;
-
- spin_lock_irqsave(&pcdev->lock, flags);
-
- cntl = readl(pcdev->base_emma + PRP_CNTL);
- if (prp->cfg.channel == 1) {
- writel(cntl & ~PRP_CNTL_CH1EN,
- pcdev->base_emma + PRP_CNTL);
- } else {
- writel(cntl & ~PRP_CNTL_CH2EN,
- pcdev->base_emma + PRP_CNTL);
- }
- INIT_LIST_HEAD(&pcdev->capture);
- INIT_LIST_HEAD(&pcdev->active_bufs);
- INIT_LIST_HEAD(&pcdev->discard);
-
- b = pcdev->discard_buffer;
- pcdev->discard_buffer = NULL;
-
- spin_unlock_irqrestore(&pcdev->lock, flags);
-
- dma_free_coherent(ici->v4l2_dev.dev,
- pcdev->discard_size, b, pcdev->discard_buffer_dma);
-}
-
-static struct vb2_ops mx2_videobuf_ops = {
- .queue_setup = mx2_videobuf_setup,
- .buf_prepare = mx2_videobuf_prepare,
- .buf_queue = mx2_videobuf_queue,
- .start_streaming = mx2_start_streaming,
- .stop_streaming = mx2_stop_streaming,
-};
-
-static int mx2_camera_init_videobuf(struct vb2_queue *q,
- struct soc_camera_device *icd)
-{
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- q->io_modes = VB2_MMAP | VB2_USERPTR;
- q->drv_priv = icd;
- q->ops = &mx2_videobuf_ops;
- q->mem_ops = &vb2_dma_contig_memops;
- q->buf_struct_size = sizeof(struct mx2_buffer);
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-
- return vb2_queue_init(q);
-}
-
-#define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \
- V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
- V4L2_MBUS_VSYNC_ACTIVE_LOW | \
- V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
- V4L2_MBUS_HSYNC_ACTIVE_LOW | \
- V4L2_MBUS_PCLK_SAMPLE_RISING | \
- V4L2_MBUS_PCLK_SAMPLE_FALLING | \
- V4L2_MBUS_DATA_ACTIVE_HIGH | \
- V4L2_MBUS_DATA_ACTIVE_LOW)
-
-static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev)
-{
- int count = 0;
-
- readl(pcdev->base_emma + PRP_CNTL);
- writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
- while (count++ < 100) {
- if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST))
- return 0;
- barrier();
- udelay(1);
- }
-
- return -ETIMEDOUT;
-}
-
-static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx2_camera_dev *pcdev = ici->priv;
- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
- unsigned long common_flags;
- int ret;
- int bytesperline;
- u32 csicr1 = pcdev->csicr1;
-
- ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
- if (!ret) {
- common_flags = soc_mbus_config_compatible(&cfg, MX2_BUS_FLAGS);
- if (!common_flags) {
- dev_warn(icd->parent,
- "Flags incompatible: camera 0x%x, host 0x%x\n",
- cfg.flags, MX2_BUS_FLAGS);
- return -EINVAL;
- }
- } else if (ret != -ENOIOCTLCMD) {
- return ret;
- } else {
- common_flags = MX2_BUS_FLAGS;
- }
-
- if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
- (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
- if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH)
- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
- else
- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
- }
-
- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
- if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING)
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
- else
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
- }
-
- cfg.flags = common_flags;
- ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
- if (ret < 0 && ret != -ENOIOCTLCMD) {
- dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
- common_flags, ret);
- return ret;
- }
-
- csicr1 = (csicr1 & ~CSICR1_FMT_MASK) | pcdev->emma_prp->cfg.csicr1;
-
- if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
- csicr1 |= CSICR1_REDGE;
- if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
- csicr1 |= CSICR1_SOF_POL;
- if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
- csicr1 |= CSICR1_HSYNC_POL;
- if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC)
- csicr1 |= CSICR1_EXT_VSYNC;
- if (pcdev->platform_flags & MX2_CAMERA_CCIR)
- csicr1 |= CSICR1_CCIR_EN;
- if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE)
- csicr1 |= CSICR1_CCIR_MODE;
- if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK)
- csicr1 |= CSICR1_GCLK_MODE;
- if (pcdev->platform_flags & MX2_CAMERA_INV_DATA)
- csicr1 |= CSICR1_INV_DATA;
-
- pcdev->csicr1 = csicr1;
-
- bytesperline = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
- if (bytesperline < 0)
- return bytesperline;
-
- ret = mx27_camera_emma_prp_reset(pcdev);
- if (ret)
- return ret;
-
- writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
-
- return 0;
-}
-
-static int mx2_camera_set_crop(struct soc_camera_device *icd,
- const struct v4l2_crop *a)
-{
- struct v4l2_crop a_writable = *a;
- struct v4l2_rect *rect = &a_writable.c;
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct v4l2_subdev_format fmt = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- };
- struct v4l2_mbus_framefmt *mf = &fmt.format;
- int ret;
-
- soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096);
- soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096);
-
- ret = v4l2_subdev_call(sd, video, s_crop, a);
- if (ret < 0)
- return ret;
-
- /* The capture device might have changed its output */
- ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
- if (ret < 0)
- return ret;
-
- dev_dbg(icd->parent, "Sensor cropped %dx%d\n",
- mf->width, mf->height);
-
- icd->user_width = mf->width;
- icd->user_height = mf->height;
-
- return ret;
-}
-
-static int mx2_camera_get_formats(struct soc_camera_device *icd,
- unsigned int idx,
- struct soc_camera_format_xlate *xlate)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_mbus_pixelfmt *fmt;
- struct device *dev = icd->parent;
- struct v4l2_subdev_mbus_code_enum code = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- .index = idx,
- };
- int ret, formats = 0;
-
- ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
- if (ret < 0)
- /* no more formats */
- return 0;
-
- fmt = soc_mbus_get_fmtdesc(code.code);
- if (!fmt) {
- dev_err(dev, "Invalid format code #%u: %d\n", idx, code.code);
- return 0;
- }
-
- if (code.code == MEDIA_BUS_FMT_YUYV8_2X8 ||
- code.code == MEDIA_BUS_FMT_UYVY8_2X8) {
- formats++;
- if (xlate) {
- /*
- * CH2 can output YUV420 which is a standard format in
- * soc_mediabus.c
- */
- xlate->host_fmt =
- soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_1_5X8);
- xlate->code = code.code;
- dev_dbg(dev, "Providing host format %s for sensor code %d\n",
- xlate->host_fmt->name, code.code);
- xlate++;
- }
- }
-
- if (code.code == MEDIA_BUS_FMT_UYVY8_2X8) {
- formats++;
- if (xlate) {
- xlate->host_fmt =
- soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_2X8);
- xlate->code = code.code;
- dev_dbg(dev, "Providing host format %s for sensor code %d\n",
- xlate->host_fmt->name, code.code);
- xlate++;
- }
- }
-
- /* Generic pass-trough */
- formats++;
- if (xlate) {
- xlate->host_fmt = fmt;
- xlate->code = code.code;
- xlate++;
- }
- return formats;
-}
-
-static int mx2_emmaprp_resize(struct mx2_camera_dev *pcdev,
- struct v4l2_mbus_framefmt *mf_in,
- struct v4l2_pix_format *pix_out, bool apply)
-{
- unsigned int num, den;
- unsigned long m;
- int i, dir;
-
- for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) {
- struct emma_prp_resize tmprsz;
- unsigned char *s = tmprsz.s;
- int len = 0;
- int in, out;
-
- if (dir == RESIZE_DIR_H) {
- in = mf_in->width;
- out = pix_out->width;
- } else {
- in = mf_in->height;
- out = pix_out->height;
- }
-
- if (in < out)
- return -EINVAL;
- else if (in == out)
- continue;
-
- /* Calculate ratio */
- m = gcd(in, out);
- num = in / m;
- den = out / m;
- if (num > RESIZE_NUM_MAX)
- return -EINVAL;
-
- if ((num >= 2 * den) && (den == 1) &&
- (num < 9) && (!(num & 0x01))) {
- int sum = 0;
- int j;
-
- /* Average scaling for >= 2:1 ratios */
- /* Support can be added for num >=9 and odd values */
-
- tmprsz.algo = RESIZE_ALGO_AVERAGING;
- len = num;
-
- for (i = 0; i < (len / 2); i++)
- s[i] = 8;
-
- do {
- for (i = 0; i < (len / 2); i++) {
- s[i] = s[i] >> 1;
- sum = 0;
- for (j = 0; j < (len / 2); j++)
- sum += s[j];
- if (sum == 4)
- break;
- }
- } while (sum != 4);
-
- for (i = (len / 2); i < len; i++)
- s[i] = s[len - i - 1];
-
- s[len - 1] |= SZ_COEF;
- } else {
- /* bilinear scaling for < 2:1 ratios */
- int v; /* overflow counter */
- int coeff, nxt; /* table output */
- int in_pos_inc = 2 * den;
- int out_pos = num;
- int out_pos_inc = 2 * num;
- int init_carry = num - den;
- int carry = init_carry;
-
- tmprsz.algo = RESIZE_ALGO_BILINEAR;
- v = den + in_pos_inc;
- do {
- coeff = v - out_pos;
- out_pos += out_pos_inc;
- carry += out_pos_inc;
- for (nxt = 0; v < out_pos; nxt++) {
- v += in_pos_inc;
- carry -= in_pos_inc;
- }
-
- if (len > RESIZE_NUM_MAX)
- return -EINVAL;
-
- coeff = ((coeff << BC_COEF) +
- (in_pos_inc >> 1)) / in_pos_inc;
-
- if (coeff >= (SZ_COEF - 1))
- coeff--;
-
- coeff |= SZ_COEF;
- s[len] = (unsigned char)coeff;
- len++;
-
- for (i = 1; i < nxt; i++) {
- if (len >= RESIZE_NUM_MAX)
- return -EINVAL;
- s[len] = 0;
- len++;
- }
- } while (carry != init_carry);
- }
- tmprsz.len = len;
- if (dir == RESIZE_DIR_H)
- mf_in->width = pix_out->width;
- else
- mf_in->height = pix_out->height;
-
- if (apply)
- memcpy(&pcdev->resizing[dir], &tmprsz, sizeof(tmprsz));
- }
- return 0;
-}
-
-static int mx2_camera_set_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx2_camera_dev *pcdev = ici->priv;
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_subdev_format format = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- };
- struct v4l2_mbus_framefmt *mf = &format.format;
- int ret;
-
- dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n",
- __func__, pix->width, pix->height);
-
- xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
- if (!xlate) {
- dev_warn(icd->parent, "Format %x not found\n",
- pix->pixelformat);
- return -EINVAL;
- }
-
- mf->width = pix->width;
- mf->height = pix->height;
- mf->field = pix->field;
- mf->colorspace = pix->colorspace;
- mf->code = xlate->code;
-
- ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
- if (ret < 0 && ret != -ENOIOCTLCMD)
- return ret;
-
- /* Store width and height returned by the sensor for resizing */
- pcdev->s_width = mf->width;
- pcdev->s_height = mf->height;
- dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n",
- __func__, pcdev->s_width, pcdev->s_height);
-
- pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code,
- xlate->host_fmt->fourcc);
-
- memset(pcdev->resizing, 0, sizeof(pcdev->resizing));
- if ((mf->width != pix->width || mf->height != pix->height) &&
- pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) {
- if (mx2_emmaprp_resize(pcdev, mf, pix, true) < 0)
- dev_dbg(icd->parent, "%s: can't resize\n", __func__);
- }
-
- if (mf->code != xlate->code)
- return -EINVAL;
-
- pix->width = mf->width;
- pix->height = mf->height;
- pix->field = mf->field;
- pix->colorspace = mf->colorspace;
- icd->current_fmt = xlate;
-
- dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n",
- __func__, pix->width, pix->height);
-
- return 0;
-}
-
-static int mx2_camera_try_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_subdev_pad_config pad_cfg;
- struct v4l2_subdev_format format = {
- .which = V4L2_SUBDEV_FORMAT_TRY,
- };
- struct v4l2_mbus_framefmt *mf = &format.format;
- __u32 pixfmt = pix->pixelformat;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx2_camera_dev *pcdev = ici->priv;
- struct mx2_fmt_cfg *emma_prp;
- int ret;
-
- dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n",
- __func__, pix->width, pix->height);
-
- xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
- if (pixfmt && !xlate) {
- dev_warn(icd->parent, "Format %x not found\n", pixfmt);
- return -EINVAL;
- }
-
- /*
- * limit to MX27 hardware capabilities: width must be a multiple of 8 as
- * requested by the CSI. (Table 39-2 in the i.MX27 Reference Manual).
- */
- pix->width &= ~0x7;
-
- /* limit to sensor capabilities */
- mf->width = pix->width;
- mf->height = pix->height;
- mf->field = pix->field;
- mf->colorspace = pix->colorspace;
- mf->code = xlate->code;
-
- ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format);
- if (ret < 0)
- return ret;
-
- dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n",
- __func__, pcdev->s_width, pcdev->s_height);
-
- /* If the sensor does not support image size try PrP resizing */
- emma_prp = mx27_emma_prp_get_format(xlate->code,
- xlate->host_fmt->fourcc);
-
- if ((mf->width != pix->width || mf->height != pix->height) &&
- emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) {
- if (mx2_emmaprp_resize(pcdev, mf, pix, false) < 0)
- dev_dbg(icd->parent, "%s: can't resize\n", __func__);
- }
-
- if (mf->field == V4L2_FIELD_ANY)
- mf->field = V4L2_FIELD_NONE;
- /*
- * Driver supports interlaced images provided they have
- * both fields so that they can be processed as if they
- * were progressive.
- */
- if (mf->field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf->field)) {
- dev_err(icd->parent, "Field type %d unsupported.\n",
- mf->field);
- return -EINVAL;
- }
-
- pix->width = mf->width;
- pix->height = mf->height;
- pix->field = mf->field;
- pix->colorspace = mf->colorspace;
-
- dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n",
- __func__, pix->width, pix->height);
-
- return 0;
-}
-
-static int mx2_camera_querycap(struct soc_camera_host *ici,
- struct v4l2_capability *cap)
-{
- /* cap->name is set by the friendly caller:-> */
- strlcpy(cap->card, MX2_CAM_DRIVER_DESCRIPTION, sizeof(cap->card));
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-
- return 0;
-}
-
-static unsigned int mx2_camera_poll(struct file *file, poll_table *pt)
-{
- struct soc_camera_device *icd = file->private_data;
-
- return vb2_poll(&icd->vb2_vidq, file, pt);
-}
-
-static struct soc_camera_host_ops mx2_soc_camera_host_ops = {
- .owner = THIS_MODULE,
- .add = mx2_camera_add_device,
- .remove = mx2_camera_remove_device,
- .clock_start = mx2_camera_clock_start,
- .clock_stop = mx2_camera_clock_stop,
- .set_fmt = mx2_camera_set_fmt,
- .set_crop = mx2_camera_set_crop,
- .get_formats = mx2_camera_get_formats,
- .try_fmt = mx2_camera_try_fmt,
- .init_videobuf2 = mx2_camera_init_videobuf,
- .poll = mx2_camera_poll,
- .querycap = mx2_camera_querycap,
- .set_bus_param = mx2_camera_set_bus_param,
-};
-
-static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
- int bufnum, bool err)
-{
-#ifdef DEBUG
- struct mx2_fmt_cfg *prp = pcdev->emma_prp;
-#endif
- struct mx2_buf_internal *ibuf;
- struct mx2_buffer *buf;
- struct vb2_buffer *vb;
- struct vb2_v4l2_buffer *vbuf;
- unsigned long phys;
-
- ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal,
- queue);
-
- BUG_ON(ibuf->bufnum != bufnum);
-
- if (ibuf->discard) {
- /*
- * Discard buffer must not be returned to user space.
- * Just return it to the discard queue.
- */
- list_move_tail(pcdev->active_bufs.next, &pcdev->discard);
- } else {
- buf = mx2_ibuf_to_buf(ibuf);
-
- vb = &buf->vb.vb2_buf;
- vbuf = to_vb2_v4l2_buffer(vb);
-#ifdef DEBUG
- phys = vb2_dma_contig_plane_dma_addr(vb, 0);
- if (prp->cfg.channel == 1) {
- if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR +
- 4 * bufnum) != phys) {
- dev_err(pcdev->dev, "%lx != %x\n", phys,
- readl(pcdev->base_emma +
- PRP_DEST_RGB1_PTR + 4 * bufnum));
- }
- } else {
- if (readl(pcdev->base_emma + PRP_DEST_Y_PTR -
- 0x14 * bufnum) != phys) {
- dev_err(pcdev->dev, "%lx != %x\n", phys,
- readl(pcdev->base_emma +
- PRP_DEST_Y_PTR - 0x14 * bufnum));
- }
- }
-#endif
- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb,
- vb2_plane_vaddr(vb, 0),
- vb2_get_plane_payload(vb, 0));
-
- list_del_init(&buf->internal.queue);
- vb->timestamp = ktime_get_ns();
- vbuf->sequence = pcdev->frame_count;
- if (err)
- vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
- else
- vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
- }
-
- pcdev->frame_count++;
-
- if (list_empty(&pcdev->capture)) {
- if (list_empty(&pcdev->discard)) {
- dev_warn(pcdev->dev, "%s: trying to access empty discard list\n",
- __func__);
- return;
- }
-
- ibuf = list_first_entry(&pcdev->discard,
- struct mx2_buf_internal, queue);
- ibuf->bufnum = bufnum;
-
- list_move_tail(pcdev->discard.next, &pcdev->active_bufs);
- mx27_update_emma_buf(pcdev, pcdev->discard_buffer_dma, bufnum);
- return;
- }
-
- buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
- internal.queue);
-
- buf->internal.bufnum = bufnum;
-
- list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
-
- vb = &buf->vb.vb2_buf;
-
- phys = vb2_dma_contig_plane_dma_addr(vb, 0);
- mx27_update_emma_buf(pcdev, phys, bufnum);
-}
-
-static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
-{
- struct mx2_camera_dev *pcdev = data;
- unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS);
- struct mx2_buf_internal *ibuf;
-
- spin_lock(&pcdev->lock);
-
- if (list_empty(&pcdev->active_bufs)) {
- dev_warn(pcdev->dev, "%s: called while active list is empty\n",
- __func__);
-
- if (!status) {
- spin_unlock(&pcdev->lock);
- return IRQ_NONE;
- }
- }
-
- if (status & (1 << 7)) { /* overflow */
- u32 cntl = readl(pcdev->base_emma + PRP_CNTL);
- writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN),
- pcdev->base_emma + PRP_CNTL);
- writel(cntl, pcdev->base_emma + PRP_CNTL);
-
- ibuf = list_first_entry(&pcdev->active_bufs,
- struct mx2_buf_internal, queue);
- mx27_camera_frame_done_emma(pcdev,
- ibuf->bufnum, true);
-
- status &= ~(1 << 7);
- } else if (((status & (3 << 5)) == (3 << 5)) ||
- ((status & (3 << 3)) == (3 << 3))) {
- /*
- * Both buffers have triggered, process the one we're expecting
- * to first
- */
- ibuf = list_first_entry(&pcdev->active_bufs,
- struct mx2_buf_internal, queue);
- mx27_camera_frame_done_emma(pcdev, ibuf->bufnum, false);
- status &= ~(1 << (6 - ibuf->bufnum)); /* mark processed */
- } else if ((status & (1 << 6)) || (status & (1 << 4))) {
- mx27_camera_frame_done_emma(pcdev, 0, false);
- } else if ((status & (1 << 5)) || (status & (1 << 3))) {
- mx27_camera_frame_done_emma(pcdev, 1, false);
- }
-
- spin_unlock(&pcdev->lock);
- writel(status, pcdev->base_emma + PRP_INTRSTATUS);
-
- return IRQ_HANDLED;
-}
-
-static int mx27_camera_emma_init(struct platform_device *pdev)
-{
- struct mx2_camera_dev *pcdev = platform_get_drvdata(pdev);
- struct resource *res_emma;
- int irq_emma;
- int err = 0;
-
- res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- irq_emma = platform_get_irq(pdev, 1);
- if (!res_emma || !irq_emma) {
- dev_err(pcdev->dev, "no EMMA resources\n");
- err = -ENODEV;
- goto out;
- }
-
- pcdev->base_emma = devm_ioremap_resource(pcdev->dev, res_emma);
- if (IS_ERR(pcdev->base_emma)) {
- err = PTR_ERR(pcdev->base_emma);
- goto out;
- }
-
- err = devm_request_irq(pcdev->dev, irq_emma, mx27_camera_emma_irq, 0,
- MX2_CAM_DRV_NAME, pcdev);
- if (err) {
- dev_err(pcdev->dev, "Camera EMMA interrupt register failed\n");
- goto out;
- }
-
- pcdev->clk_emma_ipg = devm_clk_get(pcdev->dev, "emma-ipg");
- if (IS_ERR(pcdev->clk_emma_ipg)) {
- err = PTR_ERR(pcdev->clk_emma_ipg);
- goto out;
- }
-
- clk_prepare_enable(pcdev->clk_emma_ipg);
-
- pcdev->clk_emma_ahb = devm_clk_get(pcdev->dev, "emma-ahb");
- if (IS_ERR(pcdev->clk_emma_ahb)) {
- err = PTR_ERR(pcdev->clk_emma_ahb);
- goto exit_clk_emma_ipg;
- }
-
- clk_prepare_enable(pcdev->clk_emma_ahb);
-
- err = mx27_camera_emma_prp_reset(pcdev);
- if (err)
- goto exit_clk_emma_ahb;
-
- return err;
-
-exit_clk_emma_ahb:
- clk_disable_unprepare(pcdev->clk_emma_ahb);
-exit_clk_emma_ipg:
- clk_disable_unprepare(pcdev->clk_emma_ipg);
-out:
- return err;
-}
-
-static int mx2_camera_probe(struct platform_device *pdev)
-{
- struct mx2_camera_dev *pcdev;
- struct resource *res_csi;
- int irq_csi;
- int err = 0;
-
- dev_dbg(&pdev->dev, "initialising\n");
-
- res_csi = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq_csi = platform_get_irq(pdev, 0);
- if (res_csi == NULL || irq_csi < 0) {
- dev_err(&pdev->dev, "Missing platform resources data\n");
- err = -ENODEV;
- goto exit;
- }
-
- pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
- if (!pcdev) {
- dev_err(&pdev->dev, "Could not allocate pcdev\n");
- err = -ENOMEM;
- goto exit;
- }
-
- pcdev->clk_csi_ahb = devm_clk_get(&pdev->dev, "ahb");
- if (IS_ERR(pcdev->clk_csi_ahb)) {
- dev_err(&pdev->dev, "Could not get csi ahb clock\n");
- err = PTR_ERR(pcdev->clk_csi_ahb);
- goto exit;
- }
-
- pcdev->clk_csi_per = devm_clk_get(&pdev->dev, "per");
- if (IS_ERR(pcdev->clk_csi_per)) {
- dev_err(&pdev->dev, "Could not get csi per clock\n");
- err = PTR_ERR(pcdev->clk_csi_per);
- goto exit;
- }
-
- pcdev->pdata = pdev->dev.platform_data;
- if (pcdev->pdata) {
- long rate;
-
- pcdev->platform_flags = pcdev->pdata->flags;
-
- rate = clk_round_rate(pcdev->clk_csi_per,
- pcdev->pdata->clk * 2);
- if (rate <= 0) {
- err = -ENODEV;
- goto exit;
- }
- err = clk_set_rate(pcdev->clk_csi_per, rate);
- if (err < 0)
- goto exit;
- }
-
- INIT_LIST_HEAD(&pcdev->capture);
- INIT_LIST_HEAD(&pcdev->active_bufs);
- INIT_LIST_HEAD(&pcdev->discard);
- spin_lock_init(&pcdev->lock);
-
- pcdev->base_csi = devm_ioremap_resource(&pdev->dev, res_csi);
- if (IS_ERR(pcdev->base_csi)) {
- err = PTR_ERR(pcdev->base_csi);
- goto exit;
- }
-
- pcdev->dev = &pdev->dev;
- platform_set_drvdata(pdev, pcdev);
-
- err = mx27_camera_emma_init(pdev);
- if (err)
- goto exit;
-
- /*
- * We're done with drvdata here. Clear the pointer so that
- * v4l2 core can start using drvdata on its purpose.
- */
- platform_set_drvdata(pdev, NULL);
-
- pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME,
- pcdev->soc_host.ops = &mx2_soc_camera_host_ops,
- pcdev->soc_host.priv = pcdev;
- pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
- pcdev->soc_host.nr = pdev->id;
-
- pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
- if (IS_ERR(pcdev->alloc_ctx)) {
- err = PTR_ERR(pcdev->alloc_ctx);
- goto eallocctx;
- }
- err = soc_camera_host_register(&pcdev->soc_host);
- if (err)
- goto exit_free_emma;
-
- dev_info(&pdev->dev, "MX2 Camera (CSI) driver probed, clock frequency: %ld\n",
- clk_get_rate(pcdev->clk_csi_per));
-
- return 0;
-
-exit_free_emma:
- vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
-eallocctx:
- clk_disable_unprepare(pcdev->clk_emma_ipg);
- clk_disable_unprepare(pcdev->clk_emma_ahb);
-exit:
- return err;
-}
-
-static int mx2_camera_remove(struct platform_device *pdev)
-{
- struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
- struct mx2_camera_dev *pcdev = container_of(soc_host,
- struct mx2_camera_dev, soc_host);
-
- soc_camera_host_unregister(&pcdev->soc_host);
-
- vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
-
- clk_disable_unprepare(pcdev->clk_emma_ipg);
- clk_disable_unprepare(pcdev->clk_emma_ahb);
-
- dev_info(&pdev->dev, "MX2 Camera driver unloaded\n");
-
- return 0;
-}
-
-static struct platform_driver mx2_camera_driver = {
- .driver = {
- .name = MX2_CAM_DRV_NAME,
- },
- .id_table = mx2_camera_devtype,
- .remove = mx2_camera_remove,
-};
-
-module_platform_driver_probe(mx2_camera_driver, mx2_camera_probe);
-
-MODULE_DESCRIPTION("i.MX27 SoC Camera Host driver");
-MODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(MX2_CAM_VERSION);
diff --git a/drivers/staging/media/mx3/Kconfig b/drivers/staging/media/mx3/Kconfig
deleted file mode 100644
index 595d5fe7c..000000000
--- a/drivers/staging/media/mx3/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-config VIDEO_MX3
- tristate "i.MX3x Camera Sensor Interface driver"
- depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
- depends on MX3_IPU || COMPILE_TEST
- depends on HAS_DMA
- select VIDEOBUF2_DMA_CONTIG
- ---help---
- This is a v4l2 driver for the i.MX3x Camera Sensor Interface
-
- This driver is deprecated: it should become a stand-alone driver
- instead of using the soc-camera framework.
-
- Unless someone is willing to take this on (unlikely with such
- ancient hardware) it is going to be removed from the kernel
- soon.
diff --git a/drivers/staging/media/mx3/Makefile b/drivers/staging/media/mx3/Makefile
deleted file mode 100644
index 6d91dcd80..000000000
--- a/drivers/staging/media/mx3/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# Makefile for i.MX3x Camera Sensor driver
-
-obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
diff --git a/drivers/staging/media/mx3/TODO b/drivers/staging/media/mx3/TODO
deleted file mode 100644
index bc68fa443..000000000
--- a/drivers/staging/media/mx3/TODO
+++ /dev/null
@@ -1,10 +0,0 @@
-This driver is deprecated: it should become a stand-alone driver instead of
-using the soc-camera framework.
-
-Unless someone is willing to take this on (unlikely with such ancient
-hardware) it is going to be removed from the kernel soon.
-
-Note that trivial patches will not be accepted anymore, only a full conversion.
-
-If you want to convert this driver, please contact the linux-media mailinglist
-(see http://linuxtv.org/lists.php).
diff --git a/drivers/staging/media/mx3/mx3_camera.c b/drivers/staging/media/mx3/mx3_camera.c
deleted file mode 100644
index aa39e9569..000000000
--- a/drivers/staging/media/mx3/mx3_camera.c
+++ /dev/null
@@ -1,1264 +0,0 @@
-/*
- * V4L2 Driver for i.MX3x camera host
- *
- * Copyright (C) 2008
- * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/videodev2.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/dma/ipu-dma.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-dev.h>
-#include <media/videobuf2-dma-contig.h>
-#include <media/soc_camera.h>
-#include <media/drv-intf/soc_mediabus.h>
-
-#include <linux/platform_data/media/camera-mx3.h>
-#include <linux/platform_data/dma-imx.h>
-
-#define MX3_CAM_DRV_NAME "mx3-camera"
-
-/* CMOS Sensor Interface Registers */
-#define CSI_REG_START 0x60
-
-#define CSI_SENS_CONF (0x60 - CSI_REG_START)
-#define CSI_SENS_FRM_SIZE (0x64 - CSI_REG_START)
-#define CSI_ACT_FRM_SIZE (0x68 - CSI_REG_START)
-#define CSI_OUT_FRM_CTRL (0x6C - CSI_REG_START)
-#define CSI_TST_CTRL (0x70 - CSI_REG_START)
-#define CSI_CCIR_CODE_1 (0x74 - CSI_REG_START)
-#define CSI_CCIR_CODE_2 (0x78 - CSI_REG_START)
-#define CSI_CCIR_CODE_3 (0x7C - CSI_REG_START)
-#define CSI_FLASH_STROBE_1 (0x80 - CSI_REG_START)
-#define CSI_FLASH_STROBE_2 (0x84 - CSI_REG_START)
-
-#define CSI_SENS_CONF_VSYNC_POL_SHIFT 0
-#define CSI_SENS_CONF_HSYNC_POL_SHIFT 1
-#define CSI_SENS_CONF_DATA_POL_SHIFT 2
-#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT 3
-#define CSI_SENS_CONF_SENS_PRTCL_SHIFT 4
-#define CSI_SENS_CONF_SENS_CLKSRC_SHIFT 7
-#define CSI_SENS_CONF_DATA_FMT_SHIFT 8
-#define CSI_SENS_CONF_DATA_WIDTH_SHIFT 10
-#define CSI_SENS_CONF_EXT_VSYNC_SHIFT 15
-#define CSI_SENS_CONF_DIVRATIO_SHIFT 16
-
-#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444 (0UL << CSI_SENS_CONF_DATA_FMT_SHIFT)
-#define CSI_SENS_CONF_DATA_FMT_YUV422 (2UL << CSI_SENS_CONF_DATA_FMT_SHIFT)
-#define CSI_SENS_CONF_DATA_FMT_BAYER (3UL << CSI_SENS_CONF_DATA_FMT_SHIFT)
-
-#define MAX_VIDEO_MEM 16
-
-struct mx3_camera_buffer {
- /* common v4l buffer stuff -- must be first */
- struct vb2_v4l2_buffer vb;
- struct list_head queue;
-
- /* One descriptot per scatterlist (per frame) */
- struct dma_async_tx_descriptor *txd;
-
- /* We have to "build" a scatterlist ourselves - one element per frame */
- struct scatterlist sg;
-};
-
-/**
- * struct mx3_camera_dev - i.MX3x camera (CSI) object
- * @dev: camera device, to which the coherent buffer is attached
- * @icd: currently attached camera sensor
- * @clk: pointer to clock
- * @base: remapped register base address
- * @pdata: platform data
- * @platform_flags: platform flags
- * @mclk: master clock frequency in Hz
- * @capture: list of capture videobuffers
- * @lock: protects video buffer lists
- * @active: active video buffer
- * @idmac_channel: array of pointers to IPU DMAC DMA channels
- * @soc_host: embedded soc_host object
- */
-struct mx3_camera_dev {
- /*
- * i.MX3x is only supposed to handle one camera on its Camera Sensor
- * Interface. If anyone ever builds hardware to enable more than one
- * camera _simultaneously_, they will have to modify this driver too
- */
- struct clk *clk;
-
- void __iomem *base;
-
- struct mx3_camera_pdata *pdata;
-
- unsigned long platform_flags;
- unsigned long mclk;
- u16 width_flags; /* max 15 bits */
-
- struct list_head capture;
- spinlock_t lock; /* Protects video buffer lists */
- struct mx3_camera_buffer *active;
- size_t buf_total;
- struct vb2_alloc_ctx *alloc_ctx;
- enum v4l2_field field;
- int sequence;
-
- /* IDMAC / dmaengine interface */
- struct idmac_channel *idmac_channel[1]; /* We need one channel */
-
- struct soc_camera_host soc_host;
-};
-
-struct dma_chan_request {
- struct mx3_camera_dev *mx3_cam;
- enum ipu_channel id;
-};
-
-static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg)
-{
- return __raw_readl(mx3->base + reg);
-}
-
-static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg)
-{
- __raw_writel(value, mx3->base + reg);
-}
-
-static struct mx3_camera_buffer *to_mx3_vb(struct vb2_v4l2_buffer *vb)
-{
- return container_of(vb, struct mx3_camera_buffer, vb);
-}
-
-/* Called from the IPU IDMAC ISR */
-static void mx3_cam_dma_done(void *arg)
-{
- struct idmac_tx_desc *desc = to_tx_desc(arg);
- struct dma_chan *chan = desc->txd.chan;
- struct idmac_channel *ichannel = to_idmac_chan(chan);
- struct mx3_camera_dev *mx3_cam = ichannel->client;
-
- dev_dbg(chan->device->dev, "callback cookie %d, active DMA %pad\n",
- desc->txd.cookie, mx3_cam->active ? &sg_dma_address(&mx3_cam->active->sg) : NULL);
-
- spin_lock(&mx3_cam->lock);
- if (mx3_cam->active) {
- struct vb2_v4l2_buffer *vb = &mx3_cam->active->vb;
- struct mx3_camera_buffer *buf = to_mx3_vb(vb);
-
- list_del_init(&buf->queue);
- vb->vb2_buf.timestamp = ktime_get_ns();
- vb->field = mx3_cam->field;
- vb->sequence = mx3_cam->sequence++;
- vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE);
- }
-
- if (list_empty(&mx3_cam->capture)) {
- mx3_cam->active = NULL;
- spin_unlock(&mx3_cam->lock);
-
- /*
- * stop capture - without further buffers IPU_CHA_BUF0_RDY will
- * not get updated
- */
- return;
- }
-
- mx3_cam->active = list_entry(mx3_cam->capture.next,
- struct mx3_camera_buffer, queue);
- spin_unlock(&mx3_cam->lock);
-}
-
-/*
- * Videobuf operations
- */
-
-/*
- * Calculate the __buffer__ (not data) size and number of buffers.
- */
-static int mx3_videobuf_setup(struct vb2_queue *vq,
- unsigned int *count, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
-{
- struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
-
- if (!mx3_cam->idmac_channel[0])
- return -EINVAL;
-
- alloc_ctxs[0] = mx3_cam->alloc_ctx;
-
- if (!vq->num_buffers)
- mx3_cam->sequence = 0;
-
- if (!*count)
- *count = 2;
-
- /* Called from VIDIOC_REQBUFS or in compatibility mode */
- if (!*num_planes)
- sizes[0] = icd->sizeimage;
- else if (sizes[0] < icd->sizeimage)
- return -EINVAL;
-
- /* If *num_planes != 0, we have already verified *count. */
- if (sizes[0] * *count + mx3_cam->buf_total > MAX_VIDEO_MEM * 1024 * 1024)
- *count = (MAX_VIDEO_MEM * 1024 * 1024 - mx3_cam->buf_total) /
- sizes[0];
-
- *num_planes = 1;
-
- return 0;
-}
-
-static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc)
-{
- /* Add more formats as need arises and test possibilities appear... */
- switch (fourcc) {
- case V4L2_PIX_FMT_RGB24:
- return IPU_PIX_FMT_RGB24;
- case V4L2_PIX_FMT_UYVY:
- case V4L2_PIX_FMT_RGB565:
- default:
- return IPU_PIX_FMT_GENERIC;
- }
-}
-
-static void mx3_videobuf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct mx3_camera_buffer *buf = to_mx3_vb(vbuf);
- struct scatterlist *sg = &buf->sg;
- struct dma_async_tx_descriptor *txd;
- struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
- struct idmac_video_param *video = &ichan->params.video;
- const struct soc_mbus_pixelfmt *host_fmt = icd->current_fmt->host_fmt;
- dma_cookie_t cookie;
- size_t new_size;
-
- new_size = icd->sizeimage;
-
- if (vb2_plane_size(vb, 0) < new_size) {
- dev_err(icd->parent, "Buffer #%d too small (%lu < %zu)\n",
- vbuf->vb2_buf.index, vb2_plane_size(vb, 0), new_size);
- goto error;
- }
-
- if (!buf->txd) {
- sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0);
- sg_dma_len(sg) = new_size;
-
- txd = dmaengine_prep_slave_sg(
- &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT);
- if (!txd)
- goto error;
-
- txd->callback_param = txd;
- txd->callback = mx3_cam_dma_done;
-
- buf->txd = txd;
- } else {
- txd = buf->txd;
- }
-
- vb2_set_plane_payload(vb, 0, new_size);
-
- /* This is the configuration of one sg-element */
- video->out_pixel_fmt = fourcc_to_ipu_pix(host_fmt->fourcc);
-
- if (video->out_pixel_fmt == IPU_PIX_FMT_GENERIC) {
- /*
- * If the IPU DMA channel is configured to transfer generic
- * 8-bit data, we have to set up the geometry parameters
- * correctly, according to the current pixel format. The DMA
- * horizontal parameters in this case are expressed in bytes,
- * not in pixels.
- */
- video->out_width = icd->bytesperline;
- video->out_height = icd->user_height;
- video->out_stride = icd->bytesperline;
- } else {
- /*
- * For IPU known formats the pixel unit will be managed
- * successfully by the IPU code
- */
- video->out_width = icd->user_width;
- video->out_height = icd->user_height;
- video->out_stride = icd->user_width;
- }
-
-#ifdef DEBUG
- /* helps to see what DMA actually has written */
- if (vb2_plane_vaddr(vb, 0))
- memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
-#endif
-
- spin_lock_irq(&mx3_cam->lock);
- list_add_tail(&buf->queue, &mx3_cam->capture);
-
- if (!mx3_cam->active)
- mx3_cam->active = buf;
-
- spin_unlock_irq(&mx3_cam->lock);
-
- cookie = txd->tx_submit(txd);
- dev_dbg(icd->parent, "Submitted cookie %d DMA %pad\n",
- cookie, &sg_dma_address(&buf->sg));
-
- if (cookie >= 0)
- return;
-
- spin_lock_irq(&mx3_cam->lock);
-
- /* Submit error */
- list_del_init(&buf->queue);
-
- if (mx3_cam->active == buf)
- mx3_cam->active = NULL;
-
- spin_unlock_irq(&mx3_cam->lock);
-error:
- vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
-}
-
-static void mx3_videobuf_release(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct mx3_camera_buffer *buf = to_mx3_vb(vbuf);
- struct dma_async_tx_descriptor *txd = buf->txd;
- unsigned long flags;
-
- dev_dbg(icd->parent,
- "Release%s DMA %pad, queue %sempty\n",
- mx3_cam->active == buf ? " active" : "", &sg_dma_address(&buf->sg),
- list_empty(&buf->queue) ? "" : "not ");
-
- spin_lock_irqsave(&mx3_cam->lock, flags);
-
- if (mx3_cam->active == buf)
- mx3_cam->active = NULL;
-
- /* Doesn't hurt also if the list is empty */
- list_del_init(&buf->queue);
-
- if (txd) {
- buf->txd = NULL;
- if (mx3_cam->idmac_channel[0])
- async_tx_ack(txd);
- }
-
- spin_unlock_irqrestore(&mx3_cam->lock, flags);
-
- mx3_cam->buf_total -= vb2_plane_size(vb, 0);
-}
-
-static int mx3_videobuf_init(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct mx3_camera_buffer *buf = to_mx3_vb(vbuf);
-
- if (!buf->txd) {
- /* This is for locking debugging only */
- INIT_LIST_HEAD(&buf->queue);
- sg_init_table(&buf->sg, 1);
-
- mx3_cam->buf_total += vb2_plane_size(vb, 0);
- }
-
- return 0;
-}
-
-static void mx3_stop_streaming(struct vb2_queue *q)
-{
- struct soc_camera_device *icd = soc_camera_from_vb2q(q);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
- struct mx3_camera_buffer *buf, *tmp;
- unsigned long flags;
-
- if (ichan)
- dmaengine_pause(&ichan->dma_chan);
-
- spin_lock_irqsave(&mx3_cam->lock, flags);
-
- mx3_cam->active = NULL;
-
- list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) {
- list_del_init(&buf->queue);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- }
-
- spin_unlock_irqrestore(&mx3_cam->lock, flags);
-}
-
-static struct vb2_ops mx3_videobuf_ops = {
- .queue_setup = mx3_videobuf_setup,
- .buf_queue = mx3_videobuf_queue,
- .buf_cleanup = mx3_videobuf_release,
- .buf_init = mx3_videobuf_init,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
- .stop_streaming = mx3_stop_streaming,
-};
-
-static int mx3_camera_init_videobuf(struct vb2_queue *q,
- struct soc_camera_device *icd)
-{
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- q->io_modes = VB2_MMAP | VB2_USERPTR;
- q->drv_priv = icd;
- q->ops = &mx3_videobuf_ops;
- q->mem_ops = &vb2_dma_contig_memops;
- q->buf_struct_size = sizeof(struct mx3_camera_buffer);
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->lock = &ici->host_lock;
-
- return vb2_queue_init(q);
-}
-
-/* First part of ipu_csi_init_interface() */
-static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam)
-{
- u32 conf;
- long rate;
-
- /* Set default size: ipu_csi_set_window_size() */
- csi_reg_write(mx3_cam, (640 - 1) | ((480 - 1) << 16), CSI_ACT_FRM_SIZE);
- /* ...and position to 0:0: ipu_csi_set_window_pos() */
- conf = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000;
- csi_reg_write(mx3_cam, conf, CSI_OUT_FRM_CTRL);
-
- /* We use only gated clock synchronisation mode so far */
- conf = 0 << CSI_SENS_CONF_SENS_PRTCL_SHIFT;
-
- /* Set generic data, platform-biggest bus-width */
- conf |= CSI_SENS_CONF_DATA_FMT_BAYER;
-
- if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)
- conf |= 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
- else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)
- conf |= 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
- else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)
- conf |= 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
- else/* if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)*/
- conf |= 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
-
- if (mx3_cam->platform_flags & MX3_CAMERA_CLK_SRC)
- conf |= 1 << CSI_SENS_CONF_SENS_CLKSRC_SHIFT;
- if (mx3_cam->platform_flags & MX3_CAMERA_EXT_VSYNC)
- conf |= 1 << CSI_SENS_CONF_EXT_VSYNC_SHIFT;
- if (mx3_cam->platform_flags & MX3_CAMERA_DP)
- conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT;
- if (mx3_cam->platform_flags & MX3_CAMERA_PCP)
- conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT;
- if (mx3_cam->platform_flags & MX3_CAMERA_HSP)
- conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT;
- if (mx3_cam->platform_flags & MX3_CAMERA_VSP)
- conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT;
-
- /* ipu_csi_init_interface() */
- csi_reg_write(mx3_cam, conf, CSI_SENS_CONF);
-
- clk_prepare_enable(mx3_cam->clk);
- rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk);
- dev_dbg(mx3_cam->soc_host.v4l2_dev.dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate);
- if (rate)
- clk_set_rate(mx3_cam->clk, rate);
-}
-
-static int mx3_camera_add_device(struct soc_camera_device *icd)
-{
- dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n",
- icd->devnum);
-
- return 0;
-}
-
-static void mx3_camera_remove_device(struct soc_camera_device *icd)
-{
- dev_info(icd->parent, "MX3 Camera driver detached from camera %d\n",
- icd->devnum);
-}
-
-/* Called with .host_lock held */
-static int mx3_camera_clock_start(struct soc_camera_host *ici)
-{
- struct mx3_camera_dev *mx3_cam = ici->priv;
-
- mx3_camera_activate(mx3_cam);
-
- mx3_cam->buf_total = 0;
-
- return 0;
-}
-
-/* Called with .host_lock held */
-static void mx3_camera_clock_stop(struct soc_camera_host *ici)
-{
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
-
- if (*ichan) {
- dma_release_channel(&(*ichan)->dma_chan);
- *ichan = NULL;
- }
-
- clk_disable_unprepare(mx3_cam->clk);
-}
-
-static int test_platform_param(struct mx3_camera_dev *mx3_cam,
- unsigned char buswidth, unsigned long *flags)
-{
- /*
- * If requested data width is supported by the platform, use it or any
- * possible lower value - i.MX31 is smart enough to shift bits
- */
- if (buswidth > fls(mx3_cam->width_flags))
- return -EINVAL;
-
- /*
- * Platform specified synchronization and pixel clock polarities are
- * only a recommendation and are only used during probing. MX3x
- * camera interface only works in master mode, i.e., uses HSYNC and
- * VSYNC signals from the sensor
- */
- *flags = V4L2_MBUS_MASTER |
- V4L2_MBUS_HSYNC_ACTIVE_HIGH |
- V4L2_MBUS_HSYNC_ACTIVE_LOW |
- V4L2_MBUS_VSYNC_ACTIVE_HIGH |
- V4L2_MBUS_VSYNC_ACTIVE_LOW |
- V4L2_MBUS_PCLK_SAMPLE_RISING |
- V4L2_MBUS_PCLK_SAMPLE_FALLING |
- V4L2_MBUS_DATA_ACTIVE_HIGH |
- V4L2_MBUS_DATA_ACTIVE_LOW;
-
- return 0;
-}
-
-static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
- const unsigned int depth)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
- unsigned long bus_flags, common_flags;
- int ret = test_platform_param(mx3_cam, depth, &bus_flags);
-
- dev_dbg(icd->parent, "request bus width %d bit: %d\n", depth, ret);
-
- if (ret < 0)
- return ret;
-
- ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
- if (!ret) {
- common_flags = soc_mbus_config_compatible(&cfg,
- bus_flags);
- if (!common_flags) {
- dev_warn(icd->parent,
- "Flags incompatible: camera 0x%x, host 0x%lx\n",
- cfg.flags, bus_flags);
- return -EINVAL;
- }
- } else if (ret != -ENOIOCTLCMD) {
- return ret;
- }
-
- return 0;
-}
-
-static bool chan_filter(struct dma_chan *chan, void *arg)
-{
- struct dma_chan_request *rq = arg;
- struct mx3_camera_pdata *pdata;
-
- if (!imx_dma_is_ipu(chan))
- return false;
-
- if (!rq)
- return false;
-
- pdata = rq->mx3_cam->soc_host.v4l2_dev.dev->platform_data;
-
- return rq->id == chan->chan_id &&
- pdata->dma_dev == chan->device->dev;
-}
-
-static const struct soc_mbus_pixelfmt mx3_camera_formats[] = {
- {
- .fourcc = V4L2_PIX_FMT_SBGGR8,
- .name = "Bayer BGGR (sRGB) 8 bit",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_NONE,
- .order = SOC_MBUS_ORDER_LE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- }, {
- .fourcc = V4L2_PIX_FMT_GREY,
- .name = "Monochrome 8 bit",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_NONE,
- .order = SOC_MBUS_ORDER_LE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
-};
-
-/* This will be corrected as we get more formats */
-static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
-{
- return fmt->packing == SOC_MBUS_PACKING_NONE ||
- (fmt->bits_per_sample == 8 &&
- fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
- (fmt->bits_per_sample > 8 &&
- fmt->packing == SOC_MBUS_PACKING_EXTEND16);
-}
-
-static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
- struct soc_camera_format_xlate *xlate)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct device *dev = icd->parent;
- int formats = 0, ret;
- struct v4l2_subdev_mbus_code_enum code = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- .index = idx,
- };
- const struct soc_mbus_pixelfmt *fmt;
-
- ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
- if (ret < 0)
- /* No more formats */
- return 0;
-
- fmt = soc_mbus_get_fmtdesc(code.code);
- if (!fmt) {
- dev_warn(icd->parent,
- "Unsupported format code #%u: 0x%x\n", idx, code.code);
- return 0;
- }
-
- /* This also checks support for the requested bits-per-sample */
- ret = mx3_camera_try_bus_param(icd, fmt->bits_per_sample);
- if (ret < 0)
- return 0;
-
- switch (code.code) {
- case MEDIA_BUS_FMT_SBGGR10_1X10:
- formats++;
- if (xlate) {
- xlate->host_fmt = &mx3_camera_formats[0];
- xlate->code = code.code;
- xlate++;
- dev_dbg(dev, "Providing format %s using code 0x%x\n",
- mx3_camera_formats[0].name, code.code);
- }
- break;
- case MEDIA_BUS_FMT_Y10_1X10:
- formats++;
- if (xlate) {
- xlate->host_fmt = &mx3_camera_formats[1];
- xlate->code = code.code;
- xlate++;
- dev_dbg(dev, "Providing format %s using code 0x%x\n",
- mx3_camera_formats[1].name, code.code);
- }
- break;
- default:
- if (!mx3_camera_packing_supported(fmt))
- return 0;
- }
-
- /* Generic pass-through */
- formats++;
- if (xlate) {
- xlate->host_fmt = fmt;
- xlate->code = code.code;
- dev_dbg(dev, "Providing format %c%c%c%c in pass-through mode\n",
- (fmt->fourcc >> (0*8)) & 0xFF,
- (fmt->fourcc >> (1*8)) & 0xFF,
- (fmt->fourcc >> (2*8)) & 0xFF,
- (fmt->fourcc >> (3*8)) & 0xFF);
- xlate++;
- }
-
- return formats;
-}
-
-static void configure_geometry(struct mx3_camera_dev *mx3_cam,
- unsigned int width, unsigned int height,
- const struct soc_mbus_pixelfmt *fmt)
-{
- u32 ctrl, width_field, height_field;
-
- if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) {
- /*
- * As the CSI will be configured to output BAYER, here
- * the width parameter count the number of samples to
- * capture to complete the whole image width.
- */
- unsigned int num, den;
- int ret = soc_mbus_samples_per_pixel(fmt, &num, &den);
- BUG_ON(ret < 0);
- width = width * num / den;
- }
-
- /* Setup frame size - this cannot be changed on-the-fly... */
- width_field = width - 1;
- height_field = height - 1;
- csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_SENS_FRM_SIZE);
-
- csi_reg_write(mx3_cam, width_field << 16, CSI_FLASH_STROBE_1);
- csi_reg_write(mx3_cam, (height_field << 16) | 0x22, CSI_FLASH_STROBE_2);
-
- csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_ACT_FRM_SIZE);
-
- /* ...and position */
- ctrl = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000;
- /* Sensor does the cropping */
- csi_reg_write(mx3_cam, ctrl | 0 | (0 << 8), CSI_OUT_FRM_CTRL);
-}
-
-static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam)
-{
- dma_cap_mask_t mask;
- struct dma_chan *chan;
- struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
- /* We have to use IDMAC_IC_7 for Bayer / generic data */
- struct dma_chan_request rq = {.mx3_cam = mx3_cam,
- .id = IDMAC_IC_7};
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- dma_cap_set(DMA_PRIVATE, mask);
- chan = dma_request_channel(mask, chan_filter, &rq);
- if (!chan)
- return -EBUSY;
-
- *ichan = to_idmac_chan(chan);
- (*ichan)->client = mx3_cam;
-
- return 0;
-}
-
-/*
- * FIXME: learn to use stride != width, then we can keep stride properly aligned
- * and support arbitrary (even) widths.
- */
-static inline void stride_align(__u32 *width)
-{
- if (ALIGN(*width, 8) < 4096)
- *width = ALIGN(*width, 8);
- else
- *width = *width & ~7;
-}
-
-/*
- * As long as we don't implement host-side cropping and scaling, we can use
- * default g_crop and cropcap from soc_camera.c
- */
-static int mx3_camera_set_crop(struct soc_camera_device *icd,
- const struct v4l2_crop *a)
-{
- struct v4l2_crop a_writable = *a;
- struct v4l2_rect *rect = &a_writable.c;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct v4l2_subdev_format fmt = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- };
- struct v4l2_mbus_framefmt *mf = &fmt.format;
- int ret;
-
- soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096);
- soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096);
-
- ret = v4l2_subdev_call(sd, video, s_crop, a);
- if (ret < 0)
- return ret;
-
- /* The capture device might have changed its output sizes */
- ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
- if (ret < 0)
- return ret;
-
- if (mf->code != icd->current_fmt->code)
- return -EINVAL;
-
- if (mf->width & 7) {
- /* Ouch! We can only handle 8-byte aligned width... */
- stride_align(&mf->width);
- ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &fmt);
- if (ret < 0)
- return ret;
- }
-
- if (mf->width != icd->user_width || mf->height != icd->user_height)
- configure_geometry(mx3_cam, mf->width, mf->height,
- icd->current_fmt->host_fmt);
-
- dev_dbg(icd->parent, "Sensor cropped %dx%d\n",
- mf->width, mf->height);
-
- icd->user_width = mf->width;
- icd->user_height = mf->height;
-
- return ret;
-}
-
-static int mx3_camera_set_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_subdev_format format = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- };
- struct v4l2_mbus_framefmt *mf = &format.format;
- int ret;
-
- xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
- if (!xlate) {
- dev_warn(icd->parent, "Format %x not found\n",
- pix->pixelformat);
- return -EINVAL;
- }
-
- stride_align(&pix->width);
- dev_dbg(icd->parent, "Set format %dx%d\n", pix->width, pix->height);
-
- /*
- * Might have to perform a complete interface initialisation like in
- * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
- * mxc_v4l2_s_fmt()
- */
-
- configure_geometry(mx3_cam, pix->width, pix->height, xlate->host_fmt);
-
- mf->width = pix->width;
- mf->height = pix->height;
- mf->field = pix->field;
- mf->colorspace = pix->colorspace;
- mf->code = xlate->code;
-
- ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
- if (ret < 0)
- return ret;
-
- if (mf->code != xlate->code)
- return -EINVAL;
-
- if (!mx3_cam->idmac_channel[0]) {
- ret = acquire_dma_channel(mx3_cam);
- if (ret < 0)
- return ret;
- }
-
- pix->width = mf->width;
- pix->height = mf->height;
- pix->field = mf->field;
- mx3_cam->field = mf->field;
- pix->colorspace = mf->colorspace;
- icd->current_fmt = xlate;
-
- dev_dbg(icd->parent, "Sensor set %dx%d\n", pix->width, pix->height);
-
- return ret;
-}
-
-static int mx3_camera_try_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_subdev_pad_config pad_cfg;
- struct v4l2_subdev_format format = {
- .which = V4L2_SUBDEV_FORMAT_TRY,
- };
- struct v4l2_mbus_framefmt *mf = &format.format;
- __u32 pixfmt = pix->pixelformat;
- int ret;
-
- xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
- if (pixfmt && !xlate) {
- dev_warn(icd->parent, "Format %x not found\n", pixfmt);
- return -EINVAL;
- }
-
- /* limit to MX3 hardware capabilities */
- if (pix->height > 4096)
- pix->height = 4096;
- if (pix->width > 4096)
- pix->width = 4096;
-
- /* limit to sensor capabilities */
- mf->width = pix->width;
- mf->height = pix->height;
- mf->field = pix->field;
- mf->colorspace = pix->colorspace;
- mf->code = xlate->code;
-
- ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format);
- if (ret < 0)
- return ret;
-
- pix->width = mf->width;
- pix->height = mf->height;
- pix->colorspace = mf->colorspace;
-
- switch (mf->field) {
- case V4L2_FIELD_ANY:
- pix->field = V4L2_FIELD_NONE;
- break;
- case V4L2_FIELD_NONE:
- break;
- default:
- dev_err(icd->parent, "Field type %d unsupported.\n",
- mf->field);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int mx3_camera_reqbufs(struct soc_camera_device *icd,
- struct v4l2_requestbuffers *p)
-{
- return 0;
-}
-
-static unsigned int mx3_camera_poll(struct file *file, poll_table *pt)
-{
- struct soc_camera_device *icd = file->private_data;
-
- return vb2_poll(&icd->vb2_vidq, file, pt);
-}
-
-static int mx3_camera_querycap(struct soc_camera_host *ici,
- struct v4l2_capability *cap)
-{
- /* cap->name is set by the firendly caller:-> */
- strlcpy(cap->card, "i.MX3x Camera", sizeof(cap->card));
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-
- return 0;
-}
-
-static int mx3_camera_set_bus_param(struct soc_camera_device *icd)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
- u32 pixfmt = icd->current_fmt->host_fmt->fourcc;
- unsigned long bus_flags, common_flags;
- u32 dw, sens_conf;
- const struct soc_mbus_pixelfmt *fmt;
- int buswidth;
- int ret;
- const struct soc_camera_format_xlate *xlate;
- struct device *dev = icd->parent;
-
- fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
- if (!fmt)
- return -EINVAL;
-
- xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
- if (!xlate) {
- dev_warn(dev, "Format %x not found\n", pixfmt);
- return -EINVAL;
- }
-
- buswidth = fmt->bits_per_sample;
- ret = test_platform_param(mx3_cam, buswidth, &bus_flags);
-
- dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret);
-
- if (ret < 0)
- return ret;
-
- ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
- if (!ret) {
- common_flags = soc_mbus_config_compatible(&cfg,
- bus_flags);
- if (!common_flags) {
- dev_warn(icd->parent,
- "Flags incompatible: camera 0x%x, host 0x%lx\n",
- cfg.flags, bus_flags);
- return -EINVAL;
- }
- } else if (ret != -ENOIOCTLCMD) {
- return ret;
- } else {
- common_flags = bus_flags;
- }
-
- dev_dbg(dev, "Flags cam: 0x%x host: 0x%lx common: 0x%lx\n",
- cfg.flags, bus_flags, common_flags);
-
- /* Make choices, based on platform preferences */
- if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
- (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
- if (mx3_cam->platform_flags & MX3_CAMERA_HSP)
- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
- else
- common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
- }
-
- if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
- (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
- if (mx3_cam->platform_flags & MX3_CAMERA_VSP)
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
- else
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
- }
-
- if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) &&
- (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) {
- if (mx3_cam->platform_flags & MX3_CAMERA_DP)
- common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH;
- else
- common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW;
- }
-
- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
- if (mx3_cam->platform_flags & MX3_CAMERA_PCP)
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
- else
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
- }
-
- cfg.flags = common_flags;
- ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
- if (ret < 0 && ret != -ENOIOCTLCMD) {
- dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n",
- common_flags, ret);
- return ret;
- }
-
- /*
- * So far only gated clock mode is supported. Add a line
- * (3 << CSI_SENS_CONF_SENS_PRTCL_SHIFT) |
- * below and select the required mode when supporting other
- * synchronisation protocols.
- */
- sens_conf = csi_reg_read(mx3_cam, CSI_SENS_CONF) &
- ~((1 << CSI_SENS_CONF_VSYNC_POL_SHIFT) |
- (1 << CSI_SENS_CONF_HSYNC_POL_SHIFT) |
- (1 << CSI_SENS_CONF_DATA_POL_SHIFT) |
- (1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT) |
- (3 << CSI_SENS_CONF_DATA_FMT_SHIFT) |
- (3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT));
-
- /* TODO: Support RGB and YUV formats */
-
- /* This has been set in mx3_camera_activate(), but we clear it above */
- sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER;
-
- if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
- sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT;
- if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
- sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT;
- if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
- sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT;
- if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)
- sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT;
-
- /* Just do what we're asked to do */
- switch (xlate->host_fmt->bits_per_sample) {
- case 4:
- dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
- break;
- case 8:
- dw = 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
- break;
- case 10:
- dw = 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
- break;
- default:
- /*
- * Actually it can only be 15 now, default is just to silence
- * compiler warnings
- */
- case 15:
- dw = 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
- }
-
- csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF);
-
- dev_dbg(dev, "Set SENS_CONF to %x\n", sens_conf | dw);
-
- return 0;
-}
-
-static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
- .owner = THIS_MODULE,
- .add = mx3_camera_add_device,
- .remove = mx3_camera_remove_device,
- .clock_start = mx3_camera_clock_start,
- .clock_stop = mx3_camera_clock_stop,
- .set_crop = mx3_camera_set_crop,
- .set_fmt = mx3_camera_set_fmt,
- .try_fmt = mx3_camera_try_fmt,
- .get_formats = mx3_camera_get_formats,
- .init_videobuf2 = mx3_camera_init_videobuf,
- .reqbufs = mx3_camera_reqbufs,
- .poll = mx3_camera_poll,
- .querycap = mx3_camera_querycap,
- .set_bus_param = mx3_camera_set_bus_param,
-};
-
-static int mx3_camera_probe(struct platform_device *pdev)
-{
- struct mx3_camera_pdata *pdata = pdev->dev.platform_data;
- struct mx3_camera_dev *mx3_cam;
- struct resource *res;
- void __iomem *base;
- int err = 0;
- struct soc_camera_host *soc_host;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- if (!pdata)
- return -EINVAL;
-
- mx3_cam = devm_kzalloc(&pdev->dev, sizeof(*mx3_cam), GFP_KERNEL);
- if (!mx3_cam) {
- dev_err(&pdev->dev, "Could not allocate mx3 camera object\n");
- return -ENOMEM;
- }
-
- mx3_cam->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(mx3_cam->clk))
- return PTR_ERR(mx3_cam->clk);
-
- mx3_cam->pdata = pdata;
- mx3_cam->platform_flags = pdata->flags;
- if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_MASK)) {
- /*
- * Platform hasn't set available data widths. This is bad.
- * Warn and use a default.
- */
- dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
- "data widths, using default 8 bit\n");
- mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8;
- }
- if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)
- mx3_cam->width_flags = 1 << 3;
- if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)
- mx3_cam->width_flags |= 1 << 7;
- if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)
- mx3_cam->width_flags |= 1 << 9;
- if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)
- mx3_cam->width_flags |= 1 << 14;
-
- mx3_cam->mclk = pdata->mclk_10khz * 10000;
- if (!mx3_cam->mclk) {
- dev_warn(&pdev->dev,
- "mclk_10khz == 0! Please, fix your platform data. "
- "Using default 20MHz\n");
- mx3_cam->mclk = 20000000;
- }
-
- /* list of video-buffers */
- INIT_LIST_HEAD(&mx3_cam->capture);
- spin_lock_init(&mx3_cam->lock);
-
- mx3_cam->base = base;
-
- soc_host = &mx3_cam->soc_host;
- soc_host->drv_name = MX3_CAM_DRV_NAME;
- soc_host->ops = &mx3_soc_camera_host_ops;
- soc_host->priv = mx3_cam;
- soc_host->v4l2_dev.dev = &pdev->dev;
- soc_host->nr = pdev->id;
-
- mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
- if (IS_ERR(mx3_cam->alloc_ctx))
- return PTR_ERR(mx3_cam->alloc_ctx);
-
- if (pdata->asd_sizes) {
- soc_host->asd = pdata->asd;
- soc_host->asd_sizes = pdata->asd_sizes;
- }
-
- err = soc_camera_host_register(soc_host);
- if (err)
- goto ecamhostreg;
-
- /* IDMAC interface */
- dmaengine_get();
-
- return 0;
-
-ecamhostreg:
- vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx);
- return err;
-}
-
-static int mx3_camera_remove(struct platform_device *pdev)
-{
- struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
- struct mx3_camera_dev *mx3_cam = container_of(soc_host,
- struct mx3_camera_dev, soc_host);
-
- soc_camera_host_unregister(soc_host);
-
- /*
- * The channel has either not been allocated,
- * or should have been released
- */
- if (WARN_ON(mx3_cam->idmac_channel[0]))
- dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan);
-
- vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx);
-
- dmaengine_put();
-
- return 0;
-}
-
-static struct platform_driver mx3_camera_driver = {
- .driver = {
- .name = MX3_CAM_DRV_NAME,
- },
- .probe = mx3_camera_probe,
- .remove = mx3_camera_remove,
-};
-
-module_platform_driver(mx3_camera_driver);
-
-MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
-MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.2.3");
-MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME);
diff --git a/drivers/staging/media/omap1/Kconfig b/drivers/staging/media/omap1/Kconfig
deleted file mode 100644
index 6cfab3a04..000000000
--- a/drivers/staging/media/omap1/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-config VIDEO_OMAP1
- tristate "OMAP1 Camera Interface driver"
- depends on VIDEO_DEV && SOC_CAMERA
- depends on ARCH_OMAP1
- depends on HAS_DMA
- select VIDEOBUF_DMA_CONTIG
- select VIDEOBUF_DMA_SG
- ---help---
- This is a v4l2 driver for the TI OMAP1 camera interface
-
- This driver is deprecated and will be removed soon unless someone
- will start the work to convert this driver to the vb2 framework
- and remove the soc-camera dependency.
diff --git a/drivers/staging/media/omap1/Makefile b/drivers/staging/media/omap1/Makefile
deleted file mode 100644
index 288562260..000000000
--- a/drivers/staging/media/omap1/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# Makefile for OMAP1 driver
-
-obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o
diff --git a/drivers/staging/media/omap1/TODO b/drivers/staging/media/omap1/TODO
deleted file mode 100644
index 1025f9f60..000000000
--- a/drivers/staging/media/omap1/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-This driver is deprecated and will be removed soon unless someone will start
-the work to convert this driver to the vb2 framework and remove the
-soc-camera dependency.
-
-Note that trivial patches will not be accepted anymore, only a full conversion.
-
-If you want to convert this driver, please contact the linux-media mailinglist
-(see http://linuxtv.org/lists.php).
diff --git a/drivers/staging/media/omap1/omap1_camera.c b/drivers/staging/media/omap1/omap1_camera.c
deleted file mode 100644
index 54b8dd2d2..000000000
--- a/drivers/staging/media/omap1/omap1_camera.c
+++ /dev/null
@@ -1,1702 +0,0 @@
-/*
- * V4L2 SoC Camera driver for OMAP1 Camera Interface
- *
- * Copyright (C) 2010, Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
- *
- * Based on V4L2 Driver for i.MXL/i.MXL camera (CSI) host
- * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- * Copyright (C) 2009, Darius Augulis <augulis.darius@gmail.com>
- *
- * Based on PXA SoC camera driver
- * Copyright (C) 2006, Sascha Hauer, Pengutronix
- * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
- *
- * Hardware specific bits initialy based on former work by Matt Callow
- * drivers/media/platform/omap/omap1510cam.c
- * Copyright (C) 2006 Matt Callow
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <linux/platform_data/media/omap1_camera.h>
-#include <media/soc_camera.h>
-#include <media/drv-intf/soc_mediabus.h>
-#include <media/videobuf-dma-contig.h>
-#include <media/videobuf-dma-sg.h>
-
-#include <linux/omap-dma.h>
-
-
-#define DRIVER_NAME "omap1-camera"
-#define DRIVER_VERSION "0.0.2"
-
-#define OMAP_DMA_CAMERA_IF_RX 20
-
-/*
- * ---------------------------------------------------------------------------
- * OMAP1 Camera Interface registers
- * ---------------------------------------------------------------------------
- */
-
-#define REG_CTRLCLOCK 0x00
-#define REG_IT_STATUS 0x04
-#define REG_MODE 0x08
-#define REG_STATUS 0x0C
-#define REG_CAMDATA 0x10
-#define REG_GPIO 0x14
-#define REG_PEAK_COUNTER 0x18
-
-/* CTRLCLOCK bit shifts */
-#define LCLK_EN BIT(7)
-#define DPLL_EN BIT(6)
-#define MCLK_EN BIT(5)
-#define CAMEXCLK_EN BIT(4)
-#define POLCLK BIT(3)
-#define FOSCMOD_SHIFT 0
-#define FOSCMOD_MASK (0x7 << FOSCMOD_SHIFT)
-#define FOSCMOD_12MHz 0x0
-#define FOSCMOD_6MHz 0x2
-#define FOSCMOD_9_6MHz 0x4
-#define FOSCMOD_24MHz 0x5
-#define FOSCMOD_8MHz 0x6
-
-/* IT_STATUS bit shifts */
-#define DATA_TRANSFER BIT(5)
-#define FIFO_FULL BIT(4)
-#define H_DOWN BIT(3)
-#define H_UP BIT(2)
-#define V_DOWN BIT(1)
-#define V_UP BIT(0)
-
-/* MODE bit shifts */
-#define RAZ_FIFO BIT(18)
-#define EN_FIFO_FULL BIT(17)
-#define EN_NIRQ BIT(16)
-#define THRESHOLD_SHIFT 9
-#define THRESHOLD_MASK (0x7f << THRESHOLD_SHIFT)
-#define DMA BIT(8)
-#define EN_H_DOWN BIT(7)
-#define EN_H_UP BIT(6)
-#define EN_V_DOWN BIT(5)
-#define EN_V_UP BIT(4)
-#define ORDERCAMD BIT(3)
-
-#define IRQ_MASK (EN_V_UP | EN_V_DOWN | EN_H_UP | EN_H_DOWN | \
- EN_NIRQ | EN_FIFO_FULL)
-
-/* STATUS bit shifts */
-#define HSTATUS BIT(1)
-#define VSTATUS BIT(0)
-
-/* GPIO bit shifts */
-#define CAM_RST BIT(0)
-
-/* end of OMAP1 Camera Interface registers */
-
-
-#define SOCAM_BUS_FLAGS (V4L2_MBUS_MASTER | \
- V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
- V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \
- V4L2_MBUS_DATA_ACTIVE_HIGH)
-
-
-#define FIFO_SIZE ((THRESHOLD_MASK >> THRESHOLD_SHIFT) + 1)
-#define FIFO_SHIFT __fls(FIFO_SIZE)
-
-#define DMA_BURST_SHIFT (1 + OMAP_DMA_DATA_BURST_4)
-#define DMA_BURST_SIZE (1 << DMA_BURST_SHIFT)
-
-#define DMA_ELEMENT_SHIFT OMAP_DMA_DATA_TYPE_S32
-#define DMA_ELEMENT_SIZE (1 << DMA_ELEMENT_SHIFT)
-
-#define DMA_FRAME_SHIFT_CONTIG (FIFO_SHIFT - 1)
-#define DMA_FRAME_SHIFT_SG DMA_BURST_SHIFT
-
-#define DMA_FRAME_SHIFT(x) ((x) == OMAP1_CAM_DMA_CONTIG ? \
- DMA_FRAME_SHIFT_CONTIG : \
- DMA_FRAME_SHIFT_SG)
-#define DMA_FRAME_SIZE(x) (1 << DMA_FRAME_SHIFT(x))
-#define DMA_SYNC OMAP_DMA_SYNC_FRAME
-#define THRESHOLD_LEVEL DMA_FRAME_SIZE
-
-
-#define MAX_VIDEO_MEM 4 /* arbitrary video memory limit in MB */
-
-
-/*
- * Structures
- */
-
-/* buffer for one video frame */
-struct omap1_cam_buf {
- struct videobuf_buffer vb;
- u32 code;
- int inwork;
- struct scatterlist *sgbuf;
- int sgcount;
- int bytes_left;
- enum videobuf_state result;
-};
-
-struct omap1_cam_dev {
- struct soc_camera_host soc_host;
- struct clk *clk;
-
- unsigned int irq;
- void __iomem *base;
-
- int dma_ch;
-
- struct omap1_cam_platform_data *pdata;
- struct resource *res;
- unsigned long pflags;
- unsigned long camexclk;
-
- struct list_head capture;
-
- /* lock used to protect videobuf */
- spinlock_t lock;
-
- /* Pointers to DMA buffers */
- struct omap1_cam_buf *active;
- struct omap1_cam_buf *ready;
-
- enum omap1_cam_vb_mode vb_mode;
- int (*mmap_mapper)(struct videobuf_queue *q,
- struct videobuf_buffer *buf,
- struct vm_area_struct *vma);
-
- u32 reg_cache[0];
-};
-
-
-static void cam_write(struct omap1_cam_dev *pcdev, u16 reg, u32 val)
-{
- pcdev->reg_cache[reg / sizeof(u32)] = val;
- __raw_writel(val, pcdev->base + reg);
-}
-
-static u32 cam_read(struct omap1_cam_dev *pcdev, u16 reg, bool from_cache)
-{
- return !from_cache ? __raw_readl(pcdev->base + reg) :
- pcdev->reg_cache[reg / sizeof(u32)];
-}
-
-#define CAM_READ(pcdev, reg) \
- cam_read(pcdev, REG_##reg, false)
-#define CAM_WRITE(pcdev, reg, val) \
- cam_write(pcdev, REG_##reg, val)
-#define CAM_READ_CACHE(pcdev, reg) \
- cam_read(pcdev, REG_##reg, true)
-
-/*
- * Videobuf operations
- */
-static int omap1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
- unsigned int *size)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct omap1_cam_dev *pcdev = ici->priv;
-
- *size = icd->sizeimage;
-
- if (!*count || *count < OMAP1_CAMERA_MIN_BUF_COUNT(pcdev->vb_mode))
- *count = OMAP1_CAMERA_MIN_BUF_COUNT(pcdev->vb_mode);
-
- if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
- *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
-
- dev_dbg(icd->parent,
- "%s: count=%d, size=%d\n", __func__, *count, *size);
-
- return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct omap1_cam_buf *buf,
- enum omap1_cam_vb_mode vb_mode)
-{
- struct videobuf_buffer *vb = &buf->vb;
-
- BUG_ON(in_interrupt());
-
- videobuf_waiton(vq, vb, 0, 0);
-
- if (vb_mode == OMAP1_CAM_DMA_CONTIG) {
- videobuf_dma_contig_free(vq, vb);
- } else {
- struct soc_camera_device *icd = vq->priv_data;
- struct device *dev = icd->parent;
- struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
-
- videobuf_dma_unmap(dev, dma);
- videobuf_dma_free(dma);
- }
-
- vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int omap1_videobuf_prepare(struct videobuf_queue *vq,
- struct videobuf_buffer *vb, enum v4l2_field field)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct omap1_cam_buf *buf = container_of(vb, struct omap1_cam_buf, vb);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct omap1_cam_dev *pcdev = ici->priv;
- int ret;
-
- WARN_ON(!list_empty(&vb->queue));
-
- BUG_ON(NULL == icd->current_fmt);
-
- buf->inwork = 1;
-
- if (buf->code != icd->current_fmt->code || vb->field != field ||
- vb->width != icd->user_width ||
- vb->height != icd->user_height) {
- buf->code = icd->current_fmt->code;
- vb->width = icd->user_width;
- vb->height = icd->user_height;
- vb->field = field;
- vb->state = VIDEOBUF_NEEDS_INIT;
- }
-
- vb->size = icd->sizeimage;
-
- if (vb->baddr && vb->bsize < vb->size) {
- ret = -EINVAL;
- goto out;
- }
-
- if (vb->state == VIDEOBUF_NEEDS_INIT) {
- ret = videobuf_iolock(vq, vb, NULL);
- if (ret)
- goto fail;
-
- vb->state = VIDEOBUF_PREPARED;
- }
- buf->inwork = 0;
-
- return 0;
-fail:
- free_buffer(vq, buf, pcdev->vb_mode);
-out:
- buf->inwork = 0;
- return ret;
-}
-
-static void set_dma_dest_params(int dma_ch, struct omap1_cam_buf *buf,
- enum omap1_cam_vb_mode vb_mode)
-{
- dma_addr_t dma_addr;
- unsigned int block_size;
-
- if (vb_mode == OMAP1_CAM_DMA_CONTIG) {
- dma_addr = videobuf_to_dma_contig(&buf->vb);
- block_size = buf->vb.size;
- } else {
- if (WARN_ON(!buf->sgbuf)) {
- buf->result = VIDEOBUF_ERROR;
- return;
- }
- dma_addr = sg_dma_address(buf->sgbuf);
- if (WARN_ON(!dma_addr)) {
- buf->sgbuf = NULL;
- buf->result = VIDEOBUF_ERROR;
- return;
- }
- block_size = sg_dma_len(buf->sgbuf);
- if (WARN_ON(!block_size)) {
- buf->sgbuf = NULL;
- buf->result = VIDEOBUF_ERROR;
- return;
- }
- if (unlikely(buf->bytes_left < block_size))
- block_size = buf->bytes_left;
- if (WARN_ON(dma_addr & (DMA_FRAME_SIZE(vb_mode) *
- DMA_ELEMENT_SIZE - 1))) {
- dma_addr = ALIGN(dma_addr, DMA_FRAME_SIZE(vb_mode) *
- DMA_ELEMENT_SIZE);
- block_size &= ~(DMA_FRAME_SIZE(vb_mode) *
- DMA_ELEMENT_SIZE - 1);
- }
- buf->bytes_left -= block_size;
- buf->sgcount++;
- }
-
- omap_set_dma_dest_params(dma_ch,
- OMAP_DMA_PORT_EMIFF, OMAP_DMA_AMODE_POST_INC, dma_addr, 0, 0);
- omap_set_dma_transfer_params(dma_ch,
- OMAP_DMA_DATA_TYPE_S32, DMA_FRAME_SIZE(vb_mode),
- block_size >> (DMA_FRAME_SHIFT(vb_mode) + DMA_ELEMENT_SHIFT),
- DMA_SYNC, 0, 0);
-}
-
-static struct omap1_cam_buf *prepare_next_vb(struct omap1_cam_dev *pcdev)
-{
- struct omap1_cam_buf *buf;
-
- /*
- * If there is already a buffer pointed out by the pcdev->ready,
- * (re)use it, otherwise try to fetch and configure a new one.
- */
- buf = pcdev->ready;
- if (!buf) {
- if (list_empty(&pcdev->capture))
- return buf;
- buf = list_entry(pcdev->capture.next,
- struct omap1_cam_buf, vb.queue);
- buf->vb.state = VIDEOBUF_ACTIVE;
- pcdev->ready = buf;
- list_del_init(&buf->vb.queue);
- }
-
- if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) {
- /*
- * In CONTIG mode, we can safely enter next buffer parameters
- * into the DMA programming register set after the DMA
- * has already been activated on the previous buffer
- */
- set_dma_dest_params(pcdev->dma_ch, buf, pcdev->vb_mode);
- } else {
- /*
- * In SG mode, the above is not safe since there are probably
- * a bunch of sgbufs from previous sglist still pending.
- * Instead, mark the sglist fresh for the upcoming
- * try_next_sgbuf().
- */
- buf->sgbuf = NULL;
- }
-
- return buf;
-}
-
-static struct scatterlist *try_next_sgbuf(int dma_ch, struct omap1_cam_buf *buf)
-{
- struct scatterlist *sgbuf;
-
- if (likely(buf->sgbuf)) {
- /* current sglist is active */
- if (unlikely(!buf->bytes_left)) {
- /* indicate sglist complete */
- sgbuf = NULL;
- } else {
- /* process next sgbuf */
- sgbuf = sg_next(buf->sgbuf);
- if (WARN_ON(!sgbuf)) {
- buf->result = VIDEOBUF_ERROR;
- } else if (WARN_ON(!sg_dma_len(sgbuf))) {
- sgbuf = NULL;
- buf->result = VIDEOBUF_ERROR;
- }
- }
- buf->sgbuf = sgbuf;
- } else {
- /* sglist is fresh, initialize it before using */
- struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
-
- sgbuf = dma->sglist;
- if (!(WARN_ON(!sgbuf))) {
- buf->sgbuf = sgbuf;
- buf->sgcount = 0;
- buf->bytes_left = buf->vb.size;
- buf->result = VIDEOBUF_DONE;
- }
- }
- if (sgbuf)
- /*
- * Put our next sgbuf parameters (address, size)
- * into the DMA programming register set.
- */
- set_dma_dest_params(dma_ch, buf, OMAP1_CAM_DMA_SG);
-
- return sgbuf;
-}
-
-static void start_capture(struct omap1_cam_dev *pcdev)
-{
- struct omap1_cam_buf *buf = pcdev->active;
- u32 ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK);
- u32 mode = CAM_READ_CACHE(pcdev, MODE) & ~EN_V_DOWN;
-
- if (WARN_ON(!buf))
- return;
-
- /*
- * Enable start of frame interrupt, which we will use for activating
- * our end of frame watchdog when capture actually starts.
- */
- mode |= EN_V_UP;
-
- if (unlikely(ctrlclock & LCLK_EN))
- /* stop pixel clock before FIFO reset */
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN);
- /* reset FIFO */
- CAM_WRITE(pcdev, MODE, mode | RAZ_FIFO);
-
- omap_start_dma(pcdev->dma_ch);
-
- if (pcdev->vb_mode == OMAP1_CAM_DMA_SG) {
- /*
- * In SG mode, it's a good moment for fetching next sgbuf
- * from the current sglist and, if available, already putting
- * its parameters into the DMA programming register set.
- */
- try_next_sgbuf(pcdev->dma_ch, buf);
- }
-
- /* (re)enable pixel clock */
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock | LCLK_EN);
- /* release FIFO reset */
- CAM_WRITE(pcdev, MODE, mode);
-}
-
-static void suspend_capture(struct omap1_cam_dev *pcdev)
-{
- u32 ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK);
-
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN);
- omap_stop_dma(pcdev->dma_ch);
-}
-
-static void disable_capture(struct omap1_cam_dev *pcdev)
-{
- u32 mode = CAM_READ_CACHE(pcdev, MODE);
-
- CAM_WRITE(pcdev, MODE, mode & ~(IRQ_MASK | DMA));
-}
-
-static void omap1_videobuf_queue(struct videobuf_queue *vq,
- struct videobuf_buffer *vb)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct omap1_cam_dev *pcdev = ici->priv;
- struct omap1_cam_buf *buf;
- u32 mode;
-
- list_add_tail(&vb->queue, &pcdev->capture);
- vb->state = VIDEOBUF_QUEUED;
-
- if (pcdev->active) {
- /*
- * Capture in progress, so don't touch pcdev->ready even if
- * empty. Since the transfer of the DMA programming register set
- * content to the DMA working register set is done automatically
- * by the DMA hardware, this can pretty well happen while we
- * are keeping the lock here. Leave fetching it from the queue
- * to be done when a next DMA interrupt occures instead.
- */
- return;
- }
-
- WARN_ON(pcdev->ready);
-
- buf = prepare_next_vb(pcdev);
- if (WARN_ON(!buf))
- return;
-
- pcdev->active = buf;
- pcdev->ready = NULL;
-
- dev_dbg(icd->parent,
- "%s: capture not active, setup FIFO, start DMA\n", __func__);
- mode = CAM_READ_CACHE(pcdev, MODE) & ~THRESHOLD_MASK;
- mode |= THRESHOLD_LEVEL(pcdev->vb_mode) << THRESHOLD_SHIFT;
- CAM_WRITE(pcdev, MODE, mode | EN_FIFO_FULL | DMA);
-
- if (pcdev->vb_mode == OMAP1_CAM_DMA_SG) {
- /*
- * In SG mode, the above prepare_next_vb() didn't actually
- * put anything into the DMA programming register set,
- * so we have to do it now, before activating DMA.
- */
- try_next_sgbuf(pcdev->dma_ch, buf);
- }
-
- start_capture(pcdev);
-}
-
-static void omap1_videobuf_release(struct videobuf_queue *vq,
- struct videobuf_buffer *vb)
-{
- struct omap1_cam_buf *buf =
- container_of(vb, struct omap1_cam_buf, vb);
- struct soc_camera_device *icd = vq->priv_data;
- struct device *dev = icd->parent;
- struct soc_camera_host *ici = to_soc_camera_host(dev);
- struct omap1_cam_dev *pcdev = ici->priv;
-
- switch (vb->state) {
- case VIDEOBUF_DONE:
- dev_dbg(dev, "%s (done)\n", __func__);
- break;
- case VIDEOBUF_ACTIVE:
- dev_dbg(dev, "%s (active)\n", __func__);
- break;
- case VIDEOBUF_QUEUED:
- dev_dbg(dev, "%s (queued)\n", __func__);
- break;
- case VIDEOBUF_PREPARED:
- dev_dbg(dev, "%s (prepared)\n", __func__);
- break;
- default:
- dev_dbg(dev, "%s (unknown %d)\n", __func__, vb->state);
- break;
- }
-
- free_buffer(vq, buf, pcdev->vb_mode);
-}
-
-static void videobuf_done(struct omap1_cam_dev *pcdev,
- enum videobuf_state result)
-{
- struct omap1_cam_buf *buf = pcdev->active;
- struct videobuf_buffer *vb;
- struct device *dev = pcdev->soc_host.icd->parent;
-
- if (WARN_ON(!buf)) {
- suspend_capture(pcdev);
- disable_capture(pcdev);
- return;
- }
-
- if (result == VIDEOBUF_ERROR)
- suspend_capture(pcdev);
-
- vb = &buf->vb;
- if (waitqueue_active(&vb->done)) {
- if (!pcdev->ready && result != VIDEOBUF_ERROR) {
- /*
- * No next buffer has been entered into the DMA
- * programming register set on time (could be done only
- * while the previous DMA interurpt was processed, not
- * later), so the last DMA block, be it a whole buffer
- * if in CONTIG or its last sgbuf if in SG mode, is
- * about to be reused by the just autoreinitialized DMA
- * engine, and overwritten with next frame data. Best we
- * can do is stopping the capture as soon as possible,
- * hopefully before the next frame start.
- */
- suspend_capture(pcdev);
- }
- vb->state = result;
- v4l2_get_timestamp(&vb->ts);
- if (result != VIDEOBUF_ERROR)
- vb->field_count++;
- wake_up(&vb->done);
-
- /* shift in next buffer */
- buf = pcdev->ready;
- pcdev->active = buf;
- pcdev->ready = NULL;
-
- if (!buf) {
- /*
- * No next buffer was ready on time (see above), so
- * indicate error condition to force capture restart or
- * stop, depending on next buffer already queued or not.
- */
- result = VIDEOBUF_ERROR;
- prepare_next_vb(pcdev);
-
- buf = pcdev->ready;
- pcdev->active = buf;
- pcdev->ready = NULL;
- }
- } else if (pcdev->ready) {
- /*
- * In both CONTIG and SG mode, the DMA engine has possibly
- * been already autoreinitialized with the preprogrammed
- * pcdev->ready buffer. We can either accept this fact
- * and just swap the buffers, or provoke an error condition
- * and restart capture. The former seems less intrusive.
- */
- dev_dbg(dev, "%s: nobody waiting on videobuf, swap with next\n",
- __func__);
- pcdev->active = pcdev->ready;
-
- if (pcdev->vb_mode == OMAP1_CAM_DMA_SG) {
- /*
- * In SG mode, we have to make sure that the buffer we
- * are putting back into the pcdev->ready is marked
- * fresh.
- */
- buf->sgbuf = NULL;
- }
- pcdev->ready = buf;
-
- buf = pcdev->active;
- } else {
- /*
- * No next buffer has been entered into
- * the DMA programming register set on time.
- */
- if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) {
- /*
- * In CONTIG mode, the DMA engine has already been
- * reinitialized with the current buffer. Best we can do
- * is not touching it.
- */
- dev_dbg(dev,
- "%s: nobody waiting on videobuf, reuse it\n",
- __func__);
- } else {
- /*
- * In SG mode, the DMA engine has just been
- * autoreinitialized with the last sgbuf from the
- * current list. Restart capture in order to transfer
- * next frame start into the first sgbuf, not the last
- * one.
- */
- if (result != VIDEOBUF_ERROR) {
- suspend_capture(pcdev);
- result = VIDEOBUF_ERROR;
- }
- }
- }
-
- if (!buf) {
- dev_dbg(dev, "%s: no more videobufs, stop capture\n", __func__);
- disable_capture(pcdev);
- return;
- }
-
- if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) {
- /*
- * In CONTIG mode, the current buffer parameters had already
- * been entered into the DMA programming register set while the
- * buffer was fetched with prepare_next_vb(), they may have also
- * been transferred into the runtime set and already active if
- * the DMA still running.
- */
- } else {
- /* In SG mode, extra steps are required */
- if (result == VIDEOBUF_ERROR)
- /* make sure we (re)use sglist from start on error */
- buf->sgbuf = NULL;
-
- /*
- * In any case, enter the next sgbuf parameters into the DMA
- * programming register set. They will be used either during
- * nearest DMA autoreinitialization or, in case of an error,
- * on DMA startup below.
- */
- try_next_sgbuf(pcdev->dma_ch, buf);
- }
-
- if (result == VIDEOBUF_ERROR) {
- dev_dbg(dev, "%s: videobuf error; reset FIFO, restart DMA\n",
- __func__);
- start_capture(pcdev);
- /*
- * In SG mode, the above also resulted in the next sgbuf
- * parameters being entered into the DMA programming register
- * set, making them ready for next DMA autoreinitialization.
- */
- }
-
- /*
- * Finally, try fetching next buffer.
- * In CONTIG mode, it will also enter it into the DMA programming
- * register set, making it ready for next DMA autoreinitialization.
- */
- prepare_next_vb(pcdev);
-}
-
-static void dma_isr(int channel, unsigned short status, void *data)
-{
- struct omap1_cam_dev *pcdev = data;
- struct omap1_cam_buf *buf = pcdev->active;
- unsigned long flags;
-
- spin_lock_irqsave(&pcdev->lock, flags);
-
- if (WARN_ON(!buf)) {
- suspend_capture(pcdev);
- disable_capture(pcdev);
- goto out;
- }
-
- if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) {
- /*
- * In CONTIG mode, assume we have just managed to collect the
- * whole frame, hopefully before our end of frame watchdog is
- * triggered. Then, all we have to do is disabling the watchdog
- * for this frame, and calling videobuf_done() with success
- * indicated.
- */
- CAM_WRITE(pcdev, MODE,
- CAM_READ_CACHE(pcdev, MODE) & ~EN_V_DOWN);
- videobuf_done(pcdev, VIDEOBUF_DONE);
- } else {
- /*
- * In SG mode, we have to process every sgbuf from the current
- * sglist, one after another.
- */
- if (buf->sgbuf) {
- /*
- * Current sglist not completed yet, try fetching next
- * sgbuf, hopefully putting it into the DMA programming
- * register set, making it ready for next DMA
- * autoreinitialization.
- */
- try_next_sgbuf(pcdev->dma_ch, buf);
- if (buf->sgbuf)
- goto out;
-
- /*
- * No more sgbufs left in the current sglist. This
- * doesn't mean that the whole videobuffer is already
- * complete, but only that the last sgbuf from the
- * current sglist is about to be filled. It will be
- * ready on next DMA interrupt, signalled with the
- * buf->sgbuf set back to NULL.
- */
- if (buf->result != VIDEOBUF_ERROR) {
- /*
- * Video frame collected without errors so far,
- * we can prepare for collecting a next one
- * as soon as DMA gets autoreinitialized
- * after the current (last) sgbuf is completed.
- */
- buf = prepare_next_vb(pcdev);
- if (!buf)
- goto out;
-
- try_next_sgbuf(pcdev->dma_ch, buf);
- goto out;
- }
- }
- /* end of videobuf */
- videobuf_done(pcdev, buf->result);
- }
-
-out:
- spin_unlock_irqrestore(&pcdev->lock, flags);
-}
-
-static irqreturn_t cam_isr(int irq, void *data)
-{
- struct omap1_cam_dev *pcdev = data;
- struct device *dev = pcdev->soc_host.icd->parent;
- struct omap1_cam_buf *buf = pcdev->active;
- u32 it_status;
- unsigned long flags;
-
- it_status = CAM_READ(pcdev, IT_STATUS);
- if (!it_status)
- return IRQ_NONE;
-
- spin_lock_irqsave(&pcdev->lock, flags);
-
- if (WARN_ON(!buf)) {
- dev_warn(dev, "%s: unhandled camera interrupt, status == %#x\n",
- __func__, it_status);
- suspend_capture(pcdev);
- disable_capture(pcdev);
- goto out;
- }
-
- if (unlikely(it_status & FIFO_FULL)) {
- dev_warn(dev, "%s: FIFO overflow\n", __func__);
-
- } else if (it_status & V_DOWN) {
- /* end of video frame watchdog */
- if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) {
- /*
- * In CONTIG mode, the watchdog is disabled with
- * successful DMA end of block interrupt, and reenabled
- * on next frame start. If we get here, there is nothing
- * to check, we must be out of sync.
- */
- } else {
- if (buf->sgcount == 2) {
- /*
- * If exactly 2 sgbufs from the next sglist have
- * been programmed into the DMA engine (the
- * first one already transferred into the DMA
- * runtime register set, the second one still
- * in the programming set), then we are in sync.
- */
- goto out;
- }
- }
- dev_notice(dev, "%s: unexpected end of video frame\n",
- __func__);
-
- } else if (it_status & V_UP) {
- u32 mode;
-
- if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) {
- /*
- * In CONTIG mode, we need this interrupt every frame
- * in oredr to reenable our end of frame watchdog.
- */
- mode = CAM_READ_CACHE(pcdev, MODE);
- } else {
- /*
- * In SG mode, the below enabled end of frame watchdog
- * is kept on permanently, so we can turn this one shot
- * setup off.
- */
- mode = CAM_READ_CACHE(pcdev, MODE) & ~EN_V_UP;
- }
-
- if (!(mode & EN_V_DOWN)) {
- /* (re)enable end of frame watchdog interrupt */
- mode |= EN_V_DOWN;
- }
- CAM_WRITE(pcdev, MODE, mode);
- goto out;
-
- } else {
- dev_warn(dev, "%s: unhandled camera interrupt, status == %#x\n",
- __func__, it_status);
- goto out;
- }
-
- videobuf_done(pcdev, VIDEOBUF_ERROR);
-out:
- spin_unlock_irqrestore(&pcdev->lock, flags);
- return IRQ_HANDLED;
-}
-
-static struct videobuf_queue_ops omap1_videobuf_ops = {
- .buf_setup = omap1_videobuf_setup,
- .buf_prepare = omap1_videobuf_prepare,
- .buf_queue = omap1_videobuf_queue,
- .buf_release = omap1_videobuf_release,
-};
-
-
-/*
- * SOC Camera host operations
- */
-
-static void sensor_reset(struct omap1_cam_dev *pcdev, bool reset)
-{
- /* apply/release camera sensor reset if requested by platform data */
- if (pcdev->pflags & OMAP1_CAMERA_RST_HIGH)
- CAM_WRITE(pcdev, GPIO, reset);
- else if (pcdev->pflags & OMAP1_CAMERA_RST_LOW)
- CAM_WRITE(pcdev, GPIO, !reset);
-}
-
-static int omap1_cam_add_device(struct soc_camera_device *icd)
-{
- dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n",
- icd->devnum);
-
- return 0;
-}
-
-static void omap1_cam_remove_device(struct soc_camera_device *icd)
-{
- dev_dbg(icd->parent,
- "OMAP1 Camera driver detached from camera %d\n", icd->devnum);
-}
-
-/*
- * The following two functions absolutely depend on the fact, that
- * there can be only one camera on OMAP1 camera sensor interface
- */
-static int omap1_cam_clock_start(struct soc_camera_host *ici)
-{
- struct omap1_cam_dev *pcdev = ici->priv;
- u32 ctrlclock;
-
- clk_enable(pcdev->clk);
-
- /* setup sensor clock */
- ctrlclock = CAM_READ(pcdev, CTRLCLOCK);
- ctrlclock &= ~(CAMEXCLK_EN | MCLK_EN | DPLL_EN);
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock);
-
- ctrlclock &= ~FOSCMOD_MASK;
- switch (pcdev->camexclk) {
- case 6000000:
- ctrlclock |= CAMEXCLK_EN | FOSCMOD_6MHz;
- break;
- case 8000000:
- ctrlclock |= CAMEXCLK_EN | FOSCMOD_8MHz | DPLL_EN;
- break;
- case 9600000:
- ctrlclock |= CAMEXCLK_EN | FOSCMOD_9_6MHz | DPLL_EN;
- break;
- case 12000000:
- ctrlclock |= CAMEXCLK_EN | FOSCMOD_12MHz;
- break;
- case 24000000:
- ctrlclock |= CAMEXCLK_EN | FOSCMOD_24MHz | DPLL_EN;
- default:
- break;
- }
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~DPLL_EN);
-
- /* enable internal clock */
- ctrlclock |= MCLK_EN;
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock);
-
- sensor_reset(pcdev, false);
-
- return 0;
-}
-
-static void omap1_cam_clock_stop(struct soc_camera_host *ici)
-{
- struct omap1_cam_dev *pcdev = ici->priv;
- u32 ctrlclock;
-
- suspend_capture(pcdev);
- disable_capture(pcdev);
-
- sensor_reset(pcdev, true);
-
- /* disable and release system clocks */
- ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK);
- ctrlclock &= ~(MCLK_EN | DPLL_EN | CAMEXCLK_EN);
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock);
-
- ctrlclock = (ctrlclock & ~FOSCMOD_MASK) | FOSCMOD_12MHz;
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock);
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock | MCLK_EN);
-
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~MCLK_EN);
-
- clk_disable(pcdev->clk);
-}
-
-/* Duplicate standard formats based on host capability of byte swapping */
-static const struct soc_mbus_lookup omap1_cam_formats[] = {
-{
- .code = MEDIA_BUS_FMT_UYVY8_2X8,
- .fmt = {
- .fourcc = V4L2_PIX_FMT_YUYV,
- .name = "YUYV",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_2X8_PADHI,
- .order = SOC_MBUS_ORDER_BE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
-}, {
- .code = MEDIA_BUS_FMT_VYUY8_2X8,
- .fmt = {
- .fourcc = V4L2_PIX_FMT_YVYU,
- .name = "YVYU",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_2X8_PADHI,
- .order = SOC_MBUS_ORDER_BE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
-}, {
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
- .fmt = {
- .fourcc = V4L2_PIX_FMT_UYVY,
- .name = "UYVY",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_2X8_PADHI,
- .order = SOC_MBUS_ORDER_BE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
-}, {
- .code = MEDIA_BUS_FMT_YVYU8_2X8,
- .fmt = {
- .fourcc = V4L2_PIX_FMT_VYUY,
- .name = "VYUY",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_2X8_PADHI,
- .order = SOC_MBUS_ORDER_BE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
-}, {
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
- .fmt = {
- .fourcc = V4L2_PIX_FMT_RGB555,
- .name = "RGB555",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_2X8_PADHI,
- .order = SOC_MBUS_ORDER_BE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
-}, {
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
- .fmt = {
- .fourcc = V4L2_PIX_FMT_RGB555X,
- .name = "RGB555X",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_2X8_PADHI,
- .order = SOC_MBUS_ORDER_BE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
-}, {
- .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
- .fmt = {
- .fourcc = V4L2_PIX_FMT_RGB565,
- .name = "RGB565",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_2X8_PADHI,
- .order = SOC_MBUS_ORDER_BE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
-}, {
- .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
- .fmt = {
- .fourcc = V4L2_PIX_FMT_RGB565X,
- .name = "RGB565X",
- .bits_per_sample = 8,
- .packing = SOC_MBUS_PACKING_2X8_PADHI,
- .order = SOC_MBUS_ORDER_BE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
-},
-};
-
-static int omap1_cam_get_formats(struct soc_camera_device *icd,
- unsigned int idx, struct soc_camera_format_xlate *xlate)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct device *dev = icd->parent;
- int formats = 0, ret;
- struct v4l2_subdev_mbus_code_enum code = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- .index = idx,
- };
- const struct soc_mbus_pixelfmt *fmt;
-
- ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
- if (ret < 0)
- /* No more formats */
- return 0;
-
- fmt = soc_mbus_get_fmtdesc(code.code);
- if (!fmt) {
- dev_warn(dev, "%s: unsupported format code #%d: %d\n", __func__,
- idx, code.code);
- return 0;
- }
-
- /* Check support for the requested bits-per-sample */
- if (fmt->bits_per_sample != 8)
- return 0;
-
- switch (code.code) {
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_YVYU8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
- case MEDIA_BUS_FMT_VYUY8_2X8:
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
- formats++;
- if (xlate) {
- xlate->host_fmt = soc_mbus_find_fmtdesc(code.code,
- omap1_cam_formats,
- ARRAY_SIZE(omap1_cam_formats));
- xlate->code = code.code;
- xlate++;
- dev_dbg(dev,
- "%s: providing format %s as byte swapped code #%d\n",
- __func__, xlate->host_fmt->name, code.code);
- }
- default:
- if (xlate)
- dev_dbg(dev,
- "%s: providing format %s in pass-through mode\n",
- __func__, fmt->name);
- }
- formats++;
- if (xlate) {
- xlate->host_fmt = fmt;
- xlate->code = code.code;
- xlate++;
- }
-
- return formats;
-}
-
-static bool is_dma_aligned(s32 bytes_per_line, unsigned int height,
- enum omap1_cam_vb_mode vb_mode)
-{
- int size = bytes_per_line * height;
-
- return IS_ALIGNED(bytes_per_line, DMA_ELEMENT_SIZE) &&
- IS_ALIGNED(size, DMA_FRAME_SIZE(vb_mode) * DMA_ELEMENT_SIZE);
-}
-
-static int dma_align(int *width, int *height,
- const struct soc_mbus_pixelfmt *fmt,
- enum omap1_cam_vb_mode vb_mode, bool enlarge)
-{
- s32 bytes_per_line = soc_mbus_bytes_per_line(*width, fmt);
-
- if (bytes_per_line < 0)
- return bytes_per_line;
-
- if (!is_dma_aligned(bytes_per_line, *height, vb_mode)) {
- unsigned int pxalign = __fls(bytes_per_line / *width);
- unsigned int salign = DMA_FRAME_SHIFT(vb_mode) +
- DMA_ELEMENT_SHIFT - pxalign;
- unsigned int incr = enlarge << salign;
-
- v4l_bound_align_image(width, 1, *width + incr, 0,
- height, 1, *height + incr, 0, salign);
- return 0;
- }
- return 1;
-}
-
-#define subdev_call_with_sense(pcdev, dev, icd, sd, op, function, args...) \
-({ \
- struct soc_camera_sense sense = { \
- .master_clock = pcdev->camexclk, \
- .pixel_clock_max = 0, \
- }; \
- int __ret; \
- \
- if (pcdev->pdata) \
- sense.pixel_clock_max = pcdev->pdata->lclk_khz_max * 1000; \
- icd->sense = &sense; \
- __ret = v4l2_subdev_call(sd, op, function, ##args); \
- icd->sense = NULL; \
- \
- if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { \
- if (sense.pixel_clock > sense.pixel_clock_max) { \
- dev_err(dev, \
- "%s: pixel clock %lu set by the camera too high!\n", \
- __func__, sense.pixel_clock); \
- __ret = -EINVAL; \
- } \
- } \
- __ret; \
-})
-
-static int set_format(struct omap1_cam_dev *pcdev, struct device *dev,
- struct soc_camera_device *icd, struct v4l2_subdev *sd,
- struct v4l2_subdev_format *format,
- const struct soc_camera_format_xlate *xlate)
-{
- s32 bytes_per_line;
- struct v4l2_mbus_framefmt *mf = &format->format;
- int ret = subdev_call_with_sense(pcdev, dev, icd, sd, pad, set_fmt, NULL, format);
-
- if (ret < 0) {
- dev_err(dev, "%s: set_fmt failed\n", __func__);
- return ret;
- }
-
- if (mf->code != xlate->code) {
- dev_err(dev, "%s: unexpected pixel code change\n", __func__);
- return -EINVAL;
- }
-
- bytes_per_line = soc_mbus_bytes_per_line(mf->width, xlate->host_fmt);
- if (bytes_per_line < 0) {
- dev_err(dev, "%s: soc_mbus_bytes_per_line() failed\n",
- __func__);
- return bytes_per_line;
- }
-
- if (!is_dma_aligned(bytes_per_line, mf->height, pcdev->vb_mode)) {
- dev_err(dev, "%s: resulting geometry %ux%u not DMA aligned\n",
- __func__, mf->width, mf->height);
- return -EINVAL;
- }
- return 0;
-}
-
-static int omap1_cam_set_crop(struct soc_camera_device *icd,
- const struct v4l2_crop *crop)
-{
- const struct v4l2_rect *rect = &crop->c;
- const struct soc_camera_format_xlate *xlate = icd->current_fmt;
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct device *dev = icd->parent;
- struct soc_camera_host *ici = to_soc_camera_host(dev);
- struct omap1_cam_dev *pcdev = ici->priv;
- struct v4l2_subdev_format fmt = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- };
- struct v4l2_mbus_framefmt *mf = &fmt.format;
- int ret;
-
- ret = subdev_call_with_sense(pcdev, dev, icd, sd, video, s_crop, crop);
- if (ret < 0) {
- dev_warn(dev, "%s: failed to crop to %ux%u@%u:%u\n", __func__,
- rect->width, rect->height, rect->left, rect->top);
- return ret;
- }
-
- ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
- if (ret < 0) {
- dev_warn(dev, "%s: failed to fetch current format\n", __func__);
- return ret;
- }
-
- ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode,
- false);
- if (ret < 0) {
- dev_err(dev, "%s: failed to align %ux%u %s with DMA\n",
- __func__, mf->width, mf->height,
- xlate->host_fmt->name);
- return ret;
- }
-
- if (!ret) {
- /* sensor returned geometry not DMA aligned, trying to fix */
- ret = set_format(pcdev, dev, icd, sd, &fmt, xlate);
- if (ret < 0) {
- dev_err(dev, "%s: failed to set format\n", __func__);
- return ret;
- }
- }
-
- icd->user_width = mf->width;
- icd->user_height = mf->height;
-
- return 0;
-}
-
-static int omap1_cam_set_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct device *dev = icd->parent;
- struct soc_camera_host *ici = to_soc_camera_host(dev);
- struct omap1_cam_dev *pcdev = ici->priv;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_subdev_format format = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- };
- struct v4l2_mbus_framefmt *mf = &format.format;
- int ret;
-
- xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
- if (!xlate) {
- dev_warn(dev, "%s: format %#x not found\n", __func__,
- pix->pixelformat);
- return -EINVAL;
- }
-
- mf->width = pix->width;
- mf->height = pix->height;
- mf->field = pix->field;
- mf->colorspace = pix->colorspace;
- mf->code = xlate->code;
-
- ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode,
- true);
- if (ret < 0) {
- dev_err(dev, "%s: failed to align %ux%u %s with DMA\n",
- __func__, pix->width, pix->height,
- xlate->host_fmt->name);
- return ret;
- }
-
- ret = set_format(pcdev, dev, icd, sd, &format, xlate);
- if (ret < 0) {
- dev_err(dev, "%s: failed to set format\n", __func__);
- return ret;
- }
-
- pix->width = mf->width;
- pix->height = mf->height;
- pix->field = mf->field;
- pix->colorspace = mf->colorspace;
- icd->current_fmt = xlate;
-
- return 0;
-}
-
-static int omap1_cam_try_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_subdev_pad_config pad_cfg;
- struct v4l2_subdev_format format = {
- .which = V4L2_SUBDEV_FORMAT_TRY,
- };
- struct v4l2_mbus_framefmt *mf = &format.format;
- int ret;
- /* TODO: limit to mx1 hardware capabilities */
-
- xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
- if (!xlate) {
- dev_warn(icd->parent, "Format %#x not found\n",
- pix->pixelformat);
- return -EINVAL;
- }
-
- mf->width = pix->width;
- mf->height = pix->height;
- mf->field = pix->field;
- mf->colorspace = pix->colorspace;
- mf->code = xlate->code;
-
- /* limit to sensor capabilities */
- ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format);
- if (ret < 0)
- return ret;
-
- pix->width = mf->width;
- pix->height = mf->height;
- pix->field = mf->field;
- pix->colorspace = mf->colorspace;
-
- return 0;
-}
-
-static bool sg_mode;
-
-/*
- * Local mmap_mapper wrapper,
- * used for detecting videobuf-dma-contig buffer allocation failures
- * and switching to videobuf-dma-sg automatically for future attempts.
- */
-static int omap1_cam_mmap_mapper(struct videobuf_queue *q,
- struct videobuf_buffer *buf,
- struct vm_area_struct *vma)
-{
- struct soc_camera_device *icd = q->priv_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct omap1_cam_dev *pcdev = ici->priv;
- int ret;
-
- ret = pcdev->mmap_mapper(q, buf, vma);
-
- if (ret == -ENOMEM)
- sg_mode = true;
-
- return ret;
-}
-
-static void omap1_cam_init_videobuf(struct videobuf_queue *q,
- struct soc_camera_device *icd)
-{
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct omap1_cam_dev *pcdev = ici->priv;
-
- if (!sg_mode)
- videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops,
- icd->parent, &pcdev->lock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
- sizeof(struct omap1_cam_buf), icd, &ici->host_lock);
- else
- videobuf_queue_sg_init(q, &omap1_videobuf_ops,
- icd->parent, &pcdev->lock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
- sizeof(struct omap1_cam_buf), icd, &ici->host_lock);
-
- /* use videobuf mode (auto)selected with the module parameter */
- pcdev->vb_mode = sg_mode ? OMAP1_CAM_DMA_SG : OMAP1_CAM_DMA_CONTIG;
-
- /*
- * Ensure we substitute the videobuf-dma-contig version of the
- * mmap_mapper() callback with our own wrapper, used for switching
- * automatically to videobuf-dma-sg on buffer allocation failure.
- */
- if (!sg_mode && q->int_ops->mmap_mapper != omap1_cam_mmap_mapper) {
- pcdev->mmap_mapper = q->int_ops->mmap_mapper;
- q->int_ops->mmap_mapper = omap1_cam_mmap_mapper;
- }
-}
-
-static int omap1_cam_reqbufs(struct soc_camera_device *icd,
- struct v4l2_requestbuffers *p)
-{
- int i;
-
- /*
- * This is for locking debugging only. I removed spinlocks and now I
- * check whether .prepare is ever called on a linked buffer, or whether
- * a dma IRQ can occur for an in-work or unlinked buffer. Until now
- * it hadn't triggered
- */
- for (i = 0; i < p->count; i++) {
- struct omap1_cam_buf *buf = container_of(icd->vb_vidq.bufs[i],
- struct omap1_cam_buf, vb);
- buf->inwork = 0;
- INIT_LIST_HEAD(&buf->vb.queue);
- }
-
- return 0;
-}
-
-static int omap1_cam_querycap(struct soc_camera_host *ici,
- struct v4l2_capability *cap)
-{
- /* cap->name is set by the friendly caller:-> */
- strlcpy(cap->card, "OMAP1 Camera", sizeof(cap->card));
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-
- return 0;
-}
-
-static int omap1_cam_set_bus_param(struct soc_camera_device *icd)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct device *dev = icd->parent;
- struct soc_camera_host *ici = to_soc_camera_host(dev);
- struct omap1_cam_dev *pcdev = ici->priv;
- u32 pixfmt = icd->current_fmt->host_fmt->fourcc;
- const struct soc_camera_format_xlate *xlate;
- const struct soc_mbus_pixelfmt *fmt;
- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
- unsigned long common_flags;
- u32 ctrlclock, mode;
- int ret;
-
- ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
- if (!ret) {
- common_flags = soc_mbus_config_compatible(&cfg, SOCAM_BUS_FLAGS);
- if (!common_flags) {
- dev_warn(dev,
- "Flags incompatible: camera 0x%x, host 0x%x\n",
- cfg.flags, SOCAM_BUS_FLAGS);
- return -EINVAL;
- }
- } else if (ret != -ENOIOCTLCMD) {
- return ret;
- } else {
- common_flags = SOCAM_BUS_FLAGS;
- }
-
- /* Make choices, possibly based on platform configuration */
- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
- if (!pcdev->pdata ||
- pcdev->pdata->flags & OMAP1_CAMERA_LCLK_RISING)
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
- else
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
- }
-
- cfg.flags = common_flags;
- ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
- if (ret < 0 && ret != -ENOIOCTLCMD) {
- dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n",
- common_flags, ret);
- return ret;
- }
-
- ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK);
- if (ctrlclock & LCLK_EN)
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN);
-
- if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) {
- dev_dbg(dev, "CTRLCLOCK_REG |= POLCLK\n");
- ctrlclock |= POLCLK;
- } else {
- dev_dbg(dev, "CTRLCLOCK_REG &= ~POLCLK\n");
- ctrlclock &= ~POLCLK;
- }
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN);
-
- if (ctrlclock & LCLK_EN)
- CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock);
-
- /* select bus endianness */
- xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
- fmt = xlate->host_fmt;
-
- mode = CAM_READ(pcdev, MODE) & ~(RAZ_FIFO | IRQ_MASK | DMA);
- if (fmt->order == SOC_MBUS_ORDER_LE) {
- dev_dbg(dev, "MODE_REG &= ~ORDERCAMD\n");
- CAM_WRITE(pcdev, MODE, mode & ~ORDERCAMD);
- } else {
- dev_dbg(dev, "MODE_REG |= ORDERCAMD\n");
- CAM_WRITE(pcdev, MODE, mode | ORDERCAMD);
- }
-
- return 0;
-}
-
-static unsigned int omap1_cam_poll(struct file *file, poll_table *pt)
-{
- struct soc_camera_device *icd = file->private_data;
- struct omap1_cam_buf *buf;
-
- buf = list_entry(icd->vb_vidq.stream.next, struct omap1_cam_buf,
- vb.stream);
-
- poll_wait(file, &buf->vb.done, pt);
-
- if (buf->vb.state == VIDEOBUF_DONE ||
- buf->vb.state == VIDEOBUF_ERROR)
- return POLLIN | POLLRDNORM;
-
- return 0;
-}
-
-static struct soc_camera_host_ops omap1_host_ops = {
- .owner = THIS_MODULE,
- .add = omap1_cam_add_device,
- .remove = omap1_cam_remove_device,
- .clock_start = omap1_cam_clock_start,
- .clock_stop = omap1_cam_clock_stop,
- .get_formats = omap1_cam_get_formats,
- .set_crop = omap1_cam_set_crop,
- .set_fmt = omap1_cam_set_fmt,
- .try_fmt = omap1_cam_try_fmt,
- .init_videobuf = omap1_cam_init_videobuf,
- .reqbufs = omap1_cam_reqbufs,
- .querycap = omap1_cam_querycap,
- .set_bus_param = omap1_cam_set_bus_param,
- .poll = omap1_cam_poll,
-};
-
-static int omap1_cam_probe(struct platform_device *pdev)
-{
- struct omap1_cam_dev *pcdev;
- struct resource *res;
- struct clk *clk;
- void __iomem *base;
- unsigned int irq;
- int err = 0;
-
- irq = platform_get_irq(pdev, 0);
- if ((int)irq <= 0) {
- err = -ENODEV;
- goto exit;
- }
-
- clk = devm_clk_get(&pdev->dev, "armper_ck");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev) + resource_size(res),
- GFP_KERNEL);
- if (!pcdev)
- return -ENOMEM;
-
- pcdev->clk = clk;
-
- pcdev->pdata = pdev->dev.platform_data;
- if (pcdev->pdata) {
- pcdev->pflags = pcdev->pdata->flags;
- pcdev->camexclk = pcdev->pdata->camexclk_khz * 1000;
- }
-
- switch (pcdev->camexclk) {
- case 6000000:
- case 8000000:
- case 9600000:
- case 12000000:
- case 24000000:
- break;
- default:
- /* pcdev->camexclk != 0 => pcdev->pdata != NULL */
- dev_warn(&pdev->dev,
- "Incorrect sensor clock frequency %ld kHz, "
- "should be one of 0, 6, 8, 9.6, 12 or 24 MHz, "
- "please correct your platform data\n",
- pcdev->pdata->camexclk_khz);
- pcdev->camexclk = 0;
- case 0:
- dev_info(&pdev->dev, "Not providing sensor clock\n");
- }
-
- INIT_LIST_HEAD(&pcdev->capture);
- spin_lock_init(&pcdev->lock);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- pcdev->irq = irq;
- pcdev->base = base;
-
- sensor_reset(pcdev, true);
-
- err = omap_request_dma(OMAP_DMA_CAMERA_IF_RX, DRIVER_NAME,
- dma_isr, (void *)pcdev, &pcdev->dma_ch);
- if (err < 0) {
- dev_err(&pdev->dev, "Can't request DMA for OMAP1 Camera\n");
- return -EBUSY;
- }
- dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_ch);
-
- /* preconfigure DMA */
- omap_set_dma_src_params(pcdev->dma_ch, OMAP_DMA_PORT_TIPB,
- OMAP_DMA_AMODE_CONSTANT, res->start + REG_CAMDATA,
- 0, 0);
- omap_set_dma_dest_burst_mode(pcdev->dma_ch, OMAP_DMA_DATA_BURST_4);
- /* setup DMA autoinitialization */
- omap_dma_link_lch(pcdev->dma_ch, pcdev->dma_ch);
-
- err = devm_request_irq(&pdev->dev, pcdev->irq, cam_isr, 0, DRIVER_NAME,
- pcdev);
- if (err) {
- dev_err(&pdev->dev, "Camera interrupt register failed\n");
- goto exit_free_dma;
- }
-
- pcdev->soc_host.drv_name = DRIVER_NAME;
- pcdev->soc_host.ops = &omap1_host_ops;
- pcdev->soc_host.priv = pcdev;
- pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
- pcdev->soc_host.nr = pdev->id;
-
- err = soc_camera_host_register(&pcdev->soc_host);
- if (err)
- return err;
-
- dev_info(&pdev->dev, "OMAP1 Camera Interface driver loaded\n");
-
- return 0;
-
-exit_free_dma:
- omap_free_dma(pcdev->dma_ch);
-exit:
- return err;
-}
-
-static int omap1_cam_remove(struct platform_device *pdev)
-{
- struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
- struct omap1_cam_dev *pcdev = container_of(soc_host,
- struct omap1_cam_dev, soc_host);
-
- omap_free_dma(pcdev->dma_ch);
-
- soc_camera_host_unregister(soc_host);
-
- dev_info(&pdev->dev, "OMAP1 Camera Interface driver unloaded\n");
-
- return 0;
-}
-
-static struct platform_driver omap1_cam_driver = {
- .driver = {
- .name = DRIVER_NAME,
- },
- .probe = omap1_cam_probe,
- .remove = omap1_cam_remove,
-};
-
-module_platform_driver(omap1_cam_driver);
-
-module_param(sg_mode, bool, 0644);
-MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg");
-
-MODULE_DESCRIPTION("OMAP1 Camera Interface driver");
-MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/staging/media/timb/Kconfig b/drivers/staging/media/timb/Kconfig
deleted file mode 100644
index e413fecc1..000000000
--- a/drivers/staging/media/timb/Kconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-config VIDEO_TIMBERDALE
- tristate "Support for timberdale Video In/LogiWIN"
- depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && HAS_DMA
- depends on (MFD_TIMBERDALE && TIMB_DMA) || COMPILE_TEST
- select VIDEO_ADV7180
- select VIDEOBUF_DMA_CONTIG
- ---help---
- Add support for the Video In peripherial of the timberdale FPGA.
-
- This driver is deprecated and will be removed soon unless someone
- will start the work to convert this driver to the vb2 framework.
diff --git a/drivers/staging/media/timb/Makefile b/drivers/staging/media/timb/Makefile
deleted file mode 100644
index 4c989c23a..000000000
--- a/drivers/staging/media/timb/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o
diff --git a/drivers/staging/media/timb/timblogiw.c b/drivers/staging/media/timb/timblogiw.c
deleted file mode 100644
index 113c9f3c0..000000000
--- a/drivers/staging/media/timb/timblogiw.c
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
- * timblogiw.c timberdale FPGA LogiWin Video In driver
- * Copyright (c) 2009-2010 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Supports:
- * Timberdale FPGA LogiWin Video In
- */
-
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dmaengine.h>
-#include <linux/scatterlist.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <media/videobuf-dma-contig.h>
-#include <linux/platform_data/media/timb_video.h>
-
-#define DRIVER_NAME "timb-video"
-
-#define TIMBLOGIWIN_NAME "Timberdale Video-In"
-#define TIMBLOGIW_VERSION_CODE 0x04
-
-#define TIMBLOGIW_LINES_PER_DESC 44
-#define TIMBLOGIW_MAX_VIDEO_MEM 16
-
-#define TIMBLOGIW_HAS_DECODER(lw) (lw->pdata.encoder.module_name)
-
-
-struct timblogiw {
- struct video_device video_dev;
- struct v4l2_device v4l2_dev; /* mutual exclusion */
- struct mutex lock;
- struct device *dev;
- struct timb_video_platform_data pdata;
- struct v4l2_subdev *sd_enc; /* encoder */
- bool opened;
-};
-
-struct timblogiw_tvnorm {
- v4l2_std_id std;
- u16 width;
- u16 height;
- u8 fps;
-};
-
-struct timblogiw_fh {
- struct videobuf_queue vb_vidq;
- struct timblogiw_tvnorm const *cur_norm;
- struct list_head capture;
- struct dma_chan *chan;
- spinlock_t queue_lock; /* mutual exclusion */
- unsigned int frame_count;
-};
-
-struct timblogiw_buffer {
- /* common v4l buffer stuff -- must be first */
- struct videobuf_buffer vb;
- struct scatterlist sg[16];
- dma_cookie_t cookie;
- struct timblogiw_fh *fh;
-};
-
-static const struct timblogiw_tvnorm timblogiw_tvnorms[] = {
- {
- .std = V4L2_STD_PAL,
- .width = 720,
- .height = 576,
- .fps = 25
- },
- {
- .std = V4L2_STD_NTSC,
- .width = 720,
- .height = 480,
- .fps = 30
- }
-};
-
-static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm)
-{
- return norm->width * 2;
-}
-
-
-static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm)
-{
- return norm->height * timblogiw_bytes_per_line(norm);
-}
-
-static const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
- if (timblogiw_tvnorms[i].std & std)
- return timblogiw_tvnorms + i;
-
- /* default to first element */
- return timblogiw_tvnorms;
-}
-
-static void timblogiw_dma_cb(void *data)
-{
- struct timblogiw_buffer *buf = data;
- struct timblogiw_fh *fh = buf->fh;
- struct videobuf_buffer *vb = &buf->vb;
-
- spin_lock(&fh->queue_lock);
-
- /* mark the transfer done */
- buf->cookie = -1;
-
- fh->frame_count++;
-
- if (vb->state != VIDEOBUF_ERROR) {
- list_del(&vb->queue);
- v4l2_get_timestamp(&vb->ts);
- vb->field_count = fh->frame_count * 2;
- vb->state = VIDEOBUF_DONE;
-
- wake_up(&vb->done);
- }
-
- if (!list_empty(&fh->capture)) {
- vb = list_entry(fh->capture.next, struct videobuf_buffer,
- queue);
- vb->state = VIDEOBUF_ACTIVE;
- }
-
- spin_unlock(&fh->queue_lock);
-}
-
-static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param)
-{
- return chan->chan_id == (uintptr_t)filter_param;
-}
-
-/* IOCTL functions */
-
-static int timblogiw_g_fmt(struct file *file, void *priv,
- struct v4l2_format *format)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw *lw = video_get_drvdata(vdev);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s entry\n", __func__);
-
- if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- mutex_lock(&lw->lock);
-
- format->fmt.pix.width = fh->cur_norm->width;
- format->fmt.pix.height = fh->cur_norm->height;
- format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
- format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm);
- format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm);
- format->fmt.pix.field = V4L2_FIELD_NONE;
-
- mutex_unlock(&lw->lock);
-
- return 0;
-}
-
-static int timblogiw_try_fmt(struct file *file, void *priv,
- struct v4l2_format *format)
-{
- struct video_device *vdev = video_devdata(file);
- struct v4l2_pix_format *pix = &format->fmt.pix;
-
- dev_dbg(&vdev->dev,
- "%s - width=%d, height=%d, pixelformat=%d, field=%d\n"
- "bytes per line %d, size image: %d, colorspace: %d\n",
- __func__,
- pix->width, pix->height, pix->pixelformat, pix->field,
- pix->bytesperline, pix->sizeimage, pix->colorspace);
-
- if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- if (pix->field != V4L2_FIELD_NONE)
- return -EINVAL;
-
- if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
- return -EINVAL;
-
- return 0;
-}
-
-static int timblogiw_s_fmt(struct file *file, void *priv,
- struct v4l2_format *format)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw *lw = video_get_drvdata(vdev);
- struct timblogiw_fh *fh = priv;
- struct v4l2_pix_format *pix = &format->fmt.pix;
- int err;
-
- mutex_lock(&lw->lock);
-
- err = timblogiw_try_fmt(file, priv, format);
- if (err)
- goto out;
-
- if (videobuf_queue_is_busy(&fh->vb_vidq)) {
- dev_err(&vdev->dev, "%s queue busy\n", __func__);
- err = -EBUSY;
- goto out;
- }
-
- pix->width = fh->cur_norm->width;
- pix->height = fh->cur_norm->height;
-
-out:
- mutex_unlock(&lw->lock);
- return err;
-}
-
-static int timblogiw_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- struct video_device *vdev = video_devdata(file);
-
- dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
- strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1);
- strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1);
- snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vdev->name);
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
- V4L2_CAP_READWRITE;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-
- return 0;
-}
-
-static int timblogiw_enum_fmt(struct file *file, void *priv,
- struct v4l2_fmtdesc *fmt)
-{
- struct video_device *vdev = video_devdata(file);
-
- dev_dbg(&vdev->dev, "%s, index: %d\n", __func__, fmt->index);
-
- if (fmt->index != 0)
- return -EINVAL;
- memset(fmt, 0, sizeof(*fmt));
- fmt->index = 0;
- fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- strncpy(fmt->description, "4:2:2, packed, YUYV",
- sizeof(fmt->description)-1);
- fmt->pixelformat = V4L2_PIX_FMT_UYVY;
-
- return 0;
-}
-
-static int timblogiw_g_parm(struct file *file, void *priv,
- struct v4l2_streamparm *sp)
-{
- struct timblogiw_fh *fh = priv;
- struct v4l2_captureparm *cp = &sp->parm.capture;
-
- cp->capability = V4L2_CAP_TIMEPERFRAME;
- cp->timeperframe.numerator = 1;
- cp->timeperframe.denominator = fh->cur_norm->fps;
-
- return 0;
-}
-
-static int timblogiw_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *rb)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- return videobuf_reqbufs(&fh->vb_vidq, rb);
-}
-
-static int timblogiw_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *b)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- return videobuf_querybuf(&fh->vb_vidq, b);
-}
-
-static int timblogiw_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- return videobuf_qbuf(&fh->vb_vidq, b);
-}
-
-static int timblogiw_dqbuf(struct file *file, void *priv,
- struct v4l2_buffer *b)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
-}
-
-static int timblogiw_g_std(struct file *file, void *priv, v4l2_std_id *std)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- *std = fh->cur_norm->std;
- return 0;
-}
-
-static int timblogiw_s_std(struct file *file, void *priv, v4l2_std_id std)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw *lw = video_get_drvdata(vdev);
- struct timblogiw_fh *fh = priv;
- int err = 0;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- mutex_lock(&lw->lock);
-
- if (TIMBLOGIW_HAS_DECODER(lw))
- err = v4l2_subdev_call(lw->sd_enc, video, s_std, std);
-
- if (!err)
- fh->cur_norm = timblogiw_get_norm(std);
-
- mutex_unlock(&lw->lock);
-
- return err;
-}
-
-static int timblogiw_enuminput(struct file *file, void *priv,
- struct v4l2_input *inp)
-{
- struct video_device *vdev = video_devdata(file);
- int i;
-
- dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
-
- if (inp->index != 0)
- return -EINVAL;
-
- inp->index = 0;
-
- strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1);
- inp->type = V4L2_INPUT_TYPE_CAMERA;
-
- inp->std = 0;
- for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
- inp->std |= timblogiw_tvnorms[i].std;
-
- return 0;
-}
-
-static int timblogiw_g_input(struct file *file, void *priv,
- unsigned int *input)
-{
- struct video_device *vdev = video_devdata(file);
-
- dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
-
- *input = 0;
-
- return 0;
-}
-
-static int timblogiw_s_input(struct file *file, void *priv, unsigned int input)
-{
- struct video_device *vdev = video_devdata(file);
-
- dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
-
- if (input != 0)
- return -EINVAL;
- return 0;
-}
-
-static int timblogiw_streamon(struct file *file, void *priv, enum v4l2_buf_type type)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- dev_dbg(&vdev->dev, "%s - No capture device\n", __func__);
- return -EINVAL;
- }
-
- fh->frame_count = 0;
- return videobuf_streamon(&fh->vb_vidq);
-}
-
-static int timblogiw_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s entry\n", __func__);
-
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- return videobuf_streamoff(&fh->vb_vidq);
-}
-
-static int timblogiw_querystd(struct file *file, void *priv, v4l2_std_id *std)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw *lw = video_get_drvdata(vdev);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s entry\n", __func__);
-
- if (TIMBLOGIW_HAS_DECODER(lw))
- return v4l2_subdev_call(lw->sd_enc, video, querystd, std);
- else {
- *std = fh->cur_norm->std;
- return 0;
- }
-}
-
-static int timblogiw_enum_framesizes(struct file *file, void *priv,
- struct v4l2_frmsizeenum *fsize)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = priv;
-
- dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n", __func__,
- fsize->index, fsize->pixel_format);
-
- if ((fsize->index != 0) ||
- (fsize->pixel_format != V4L2_PIX_FMT_UYVY))
- return -EINVAL;
-
- fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
- fsize->discrete.width = fh->cur_norm->width;
- fsize->discrete.height = fh->cur_norm->height;
-
- return 0;
-}
-
-/* Video buffer functions */
-
-static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
- unsigned int *size)
-{
- struct timblogiw_fh *fh = vq->priv_data;
-
- *size = timblogiw_frame_size(fh->cur_norm);
-
- if (!*count)
- *count = 32;
-
- while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024)
- (*count)--;
-
- return 0;
-}
-
-static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
- enum v4l2_field field)
-{
- struct timblogiw_fh *fh = vq->priv_data;
- struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
- vb);
- unsigned int data_size = timblogiw_frame_size(fh->cur_norm);
- int err = 0;
-
- if (vb->baddr && vb->bsize < data_size)
- /* User provided buffer, but it is too small */
- return -ENOMEM;
-
- vb->size = data_size;
- vb->width = fh->cur_norm->width;
- vb->height = fh->cur_norm->height;
- vb->field = field;
-
- if (vb->state == VIDEOBUF_NEEDS_INIT) {
- int i;
- unsigned int size;
- unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
- timblogiw_bytes_per_line(fh->cur_norm);
- dma_addr_t addr;
-
- sg_init_table(buf->sg, ARRAY_SIZE(buf->sg));
-
- err = videobuf_iolock(vq, vb, NULL);
- if (err)
- goto err;
-
- addr = videobuf_to_dma_contig(vb);
- for (i = 0, size = 0; size < data_size; i++) {
- sg_dma_address(buf->sg + i) = addr + size;
- size += bytes_per_desc;
- sg_dma_len(buf->sg + i) = (size > data_size) ?
- (bytes_per_desc - (size - data_size)) :
- bytes_per_desc;
- }
-
- vb->state = VIDEOBUF_PREPARED;
- buf->cookie = -1;
- buf->fh = fh;
- }
-
- return 0;
-
-err:
- videobuf_dma_contig_free(vq, vb);
- vb->state = VIDEOBUF_NEEDS_INIT;
- return err;
-}
-
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
- struct timblogiw_fh *fh = vq->priv_data;
- struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
- vb);
- struct dma_async_tx_descriptor *desc;
- int sg_elems;
- int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
- timblogiw_bytes_per_line(fh->cur_norm);
-
- sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc;
- sg_elems +=
- (timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0;
-
- if (list_empty(&fh->capture))
- vb->state = VIDEOBUF_ACTIVE;
- else
- vb->state = VIDEOBUF_QUEUED;
-
- list_add_tail(&vb->queue, &fh->capture);
-
- spin_unlock_irq(&fh->queue_lock);
-
- desc = dmaengine_prep_slave_sg(fh->chan,
- buf->sg, sg_elems, DMA_DEV_TO_MEM,
- DMA_PREP_INTERRUPT);
- if (!desc) {
- spin_lock_irq(&fh->queue_lock);
- list_del_init(&vb->queue);
- vb->state = VIDEOBUF_PREPARED;
- return;
- }
-
- desc->callback_param = buf;
- desc->callback = timblogiw_dma_cb;
-
- buf->cookie = desc->tx_submit(desc);
-
- spin_lock_irq(&fh->queue_lock);
-}
-
-static void buffer_release(struct videobuf_queue *vq,
- struct videobuf_buffer *vb)
-{
- struct timblogiw_fh *fh = vq->priv_data;
- struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
- vb);
-
- videobuf_waiton(vq, vb, 0, 0);
- if (buf->cookie >= 0)
- dma_sync_wait(fh->chan, buf->cookie);
-
- videobuf_dma_contig_free(vq, vb);
- vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-static struct videobuf_queue_ops timblogiw_video_qops = {
- .buf_setup = buffer_setup,
- .buf_prepare = buffer_prepare,
- .buf_queue = buffer_queue,
- .buf_release = buffer_release,
-};
-
-/* Device Operations functions */
-
-static int timblogiw_open(struct file *file)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw *lw = video_get_drvdata(vdev);
- struct timblogiw_fh *fh;
- v4l2_std_id std;
- dma_cap_mask_t mask;
- int err = 0;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- mutex_lock(&lw->lock);
- if (lw->opened) {
- err = -EBUSY;
- goto out;
- }
-
- if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) {
- struct i2c_adapter *adapt;
-
- /* find the video decoder */
- adapt = i2c_get_adapter(lw->pdata.i2c_adapter);
- if (!adapt) {
- dev_err(&vdev->dev, "No I2C bus #%d\n",
- lw->pdata.i2c_adapter);
- err = -ENODEV;
- goto out;
- }
-
- /* now find the encoder */
- lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt,
- lw->pdata.encoder.info, NULL);
-
- i2c_put_adapter(adapt);
-
- if (!lw->sd_enc) {
- dev_err(&vdev->dev, "Failed to get encoder: %s\n",
- lw->pdata.encoder.module_name);
- err = -ENODEV;
- goto out;
- }
- }
-
- fh = kzalloc(sizeof(*fh), GFP_KERNEL);
- if (!fh) {
- err = -ENOMEM;
- goto out;
- }
-
- fh->cur_norm = timblogiw_tvnorms;
- timblogiw_querystd(file, fh, &std);
- fh->cur_norm = timblogiw_get_norm(std);
-
- INIT_LIST_HEAD(&fh->capture);
- spin_lock_init(&fh->queue_lock);
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- dma_cap_set(DMA_PRIVATE, mask);
-
- /* find the DMA channel */
- fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn,
- (void *)(uintptr_t)lw->pdata.dma_channel);
- if (!fh->chan) {
- dev_err(&vdev->dev, "Failed to get DMA channel\n");
- kfree(fh);
- err = -ENODEV;
- goto out;
- }
-
- file->private_data = fh;
- videobuf_queue_dma_contig_init(&fh->vb_vidq,
- &timblogiw_video_qops, lw->dev, &fh->queue_lock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
- sizeof(struct timblogiw_buffer), fh, NULL);
-
- lw->opened = true;
-out:
- mutex_unlock(&lw->lock);
-
- return err;
-}
-
-static int timblogiw_close(struct file *file)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw *lw = video_get_drvdata(vdev);
- struct timblogiw_fh *fh = file->private_data;
-
- dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
-
- videobuf_stop(&fh->vb_vidq);
- videobuf_mmap_free(&fh->vb_vidq);
-
- dma_release_channel(fh->chan);
-
- kfree(fh);
-
- mutex_lock(&lw->lock);
- lw->opened = false;
- mutex_unlock(&lw->lock);
- return 0;
-}
-
-static ssize_t timblogiw_read(struct file *file, char __user *data,
- size_t count, loff_t *ppos)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = file->private_data;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
- file->f_flags & O_NONBLOCK);
-}
-
-static unsigned int timblogiw_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = file->private_data;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- return videobuf_poll_stream(file, &fh->vb_vidq, wait);
-}
-
-static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct video_device *vdev = video_devdata(file);
- struct timblogiw_fh *fh = file->private_data;
-
- dev_dbg(&vdev->dev, "%s: entry\n", __func__);
-
- return videobuf_mmap_mapper(&fh->vb_vidq, vma);
-}
-
-/* Platform device functions */
-
-static struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
- .vidioc_querycap = timblogiw_querycap,
- .vidioc_enum_fmt_vid_cap = timblogiw_enum_fmt,
- .vidioc_g_fmt_vid_cap = timblogiw_g_fmt,
- .vidioc_try_fmt_vid_cap = timblogiw_try_fmt,
- .vidioc_s_fmt_vid_cap = timblogiw_s_fmt,
- .vidioc_g_parm = timblogiw_g_parm,
- .vidioc_reqbufs = timblogiw_reqbufs,
- .vidioc_querybuf = timblogiw_querybuf,
- .vidioc_qbuf = timblogiw_qbuf,
- .vidioc_dqbuf = timblogiw_dqbuf,
- .vidioc_g_std = timblogiw_g_std,
- .vidioc_s_std = timblogiw_s_std,
- .vidioc_enum_input = timblogiw_enuminput,
- .vidioc_g_input = timblogiw_g_input,
- .vidioc_s_input = timblogiw_s_input,
- .vidioc_streamon = timblogiw_streamon,
- .vidioc_streamoff = timblogiw_streamoff,
- .vidioc_querystd = timblogiw_querystd,
- .vidioc_enum_framesizes = timblogiw_enum_framesizes,
-};
-
-static struct v4l2_file_operations timblogiw_fops = {
- .owner = THIS_MODULE,
- .open = timblogiw_open,
- .release = timblogiw_close,
- .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
- .mmap = timblogiw_mmap,
- .read = timblogiw_read,
- .poll = timblogiw_poll,
-};
-
-static struct video_device timblogiw_template = {
- .name = TIMBLOGIWIN_NAME,
- .fops = &timblogiw_fops,
- .ioctl_ops = &timblogiw_ioctl_ops,
- .release = video_device_release_empty,
- .minor = -1,
- .tvnorms = V4L2_STD_PAL | V4L2_STD_NTSC
-};
-
-static int timblogiw_probe(struct platform_device *pdev)
-{
- int err;
- struct timblogiw *lw = NULL;
- struct timb_video_platform_data *pdata = pdev->dev.platform_data;
-
- if (!pdata) {
- dev_err(&pdev->dev, "No platform data\n");
- err = -EINVAL;
- goto err;
- }
-
- if (!pdata->encoder.module_name)
- dev_info(&pdev->dev, "Running without decoder\n");
-
- lw = devm_kzalloc(&pdev->dev, sizeof(*lw), GFP_KERNEL);
- if (!lw) {
- err = -ENOMEM;
- goto err;
- }
-
- if (pdev->dev.parent)
- lw->dev = pdev->dev.parent;
- else
- lw->dev = &pdev->dev;
-
- memcpy(&lw->pdata, pdata, sizeof(lw->pdata));
-
- mutex_init(&lw->lock);
-
- lw->video_dev = timblogiw_template;
-
- strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name));
- err = v4l2_device_register(NULL, &lw->v4l2_dev);
- if (err)
- goto err;
-
- lw->video_dev.v4l2_dev = &lw->v4l2_dev;
-
- platform_set_drvdata(pdev, lw);
- video_set_drvdata(&lw->video_dev, lw);
-
- err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0);
- if (err) {
- dev_err(&pdev->dev, "Error reg video: %d\n", err);
- goto err_request;
- }
-
- return 0;
-
-err_request:
- v4l2_device_unregister(&lw->v4l2_dev);
-err:
- dev_err(&pdev->dev, "Failed to register: %d\n", err);
-
- return err;
-}
-
-static int timblogiw_remove(struct platform_device *pdev)
-{
- struct timblogiw *lw = platform_get_drvdata(pdev);
-
- video_unregister_device(&lw->video_dev);
-
- v4l2_device_unregister(&lw->v4l2_dev);
-
- return 0;
-}
-
-static struct platform_driver timblogiw_platform_driver = {
- .driver = {
- .name = DRIVER_NAME,
- },
- .probe = timblogiw_probe,
- .remove = timblogiw_remove,
-};
-
-module_platform_driver(timblogiw_platform_driver);
-
-MODULE_DESCRIPTION(TIMBLOGIWIN_NAME);
-MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:"DRIVER_NAME);
diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c
deleted file mode 100644
index 6cb894e58..000000000
--- a/drivers/staging/wilc1000/wilc_msgqueue.c
+++ /dev/null
@@ -1,144 +0,0 @@
-
-#include "wilc_msgqueue.h"
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-/*!
- * @author syounan
- * @date 1 Sep 2010
- * @note copied from FLO glue implementatuion
- * @version 1.0
- */
-int wilc_mq_create(struct message_queue *mq)
-{
- spin_lock_init(&mq->lock);
- sema_init(&mq->sem, 0);
- INIT_LIST_HEAD(&mq->msg_list);
- mq->recv_count = 0;
- mq->exiting = false;
- return 0;
-}
-
-/*!
- * @author syounan
- * @date 1 Sep 2010
- * @note copied from FLO glue implementatuion
- * @version 1.0
- */
-int wilc_mq_destroy(struct message_queue *mq)
-{
- struct message *msg;
-
- mq->exiting = true;
-
- /* Release any waiting receiver thread. */
- while (mq->recv_count > 0) {
- up(&mq->sem);
- mq->recv_count--;
- }
-
- while (!list_empty(&mq->msg_list)) {
- msg = list_first_entry(&mq->msg_list, struct message, list);
- list_del(&msg->list);
- kfree(msg->buf);
- }
-
- return 0;
-}
-
-/*!
- * @author syounan
- * @date 1 Sep 2010
- * @note copied from FLO glue implementatuion
- * @version 1.0
- */
-int wilc_mq_send(struct message_queue *mq,
- const void *send_buf, u32 send_buf_size)
-{
- unsigned long flags;
- struct message *new_msg = NULL;
-
- if (!mq || (send_buf_size == 0) || !send_buf)
- return -EINVAL;
-
- if (mq->exiting)
- return -EFAULT;
-
- /* construct a new message */
- new_msg = kmalloc(sizeof(*new_msg), GFP_ATOMIC);
- if (!new_msg)
- return -ENOMEM;
-
- new_msg->len = send_buf_size;
- INIT_LIST_HEAD(&new_msg->list);
- new_msg->buf = kmemdup(send_buf, send_buf_size, GFP_ATOMIC);
- if (!new_msg->buf) {
- kfree(new_msg);
- return -ENOMEM;
- }
-
- spin_lock_irqsave(&mq->lock, flags);
-
- /* add it to the message queue */
- list_add_tail(&new_msg->list, &mq->msg_list);
-
- spin_unlock_irqrestore(&mq->lock, flags);
-
- up(&mq->sem);
-
- return 0;
-}
-
-/*!
- * @author syounan
- * @date 1 Sep 2010
- * @note copied from FLO glue implementatuion
- * @version 1.0
- */
-int wilc_mq_recv(struct message_queue *mq,
- void *recv_buf, u32 recv_buf_size, u32 *recv_len)
-{
- struct message *msg;
- unsigned long flags;
-
- if (!mq || (recv_buf_size == 0) || !recv_buf || !recv_len)
- return -EINVAL;
-
- if (mq->exiting)
- return -EFAULT;
-
- spin_lock_irqsave(&mq->lock, flags);
- mq->recv_count++;
- spin_unlock_irqrestore(&mq->lock, flags);
-
- down(&mq->sem);
- spin_lock_irqsave(&mq->lock, flags);
-
- if (list_empty(&mq->msg_list)) {
- spin_unlock_irqrestore(&mq->lock, flags);
- up(&mq->sem);
- return -EFAULT;
- }
- /* check buffer size */
- msg = list_first_entry(&mq->msg_list, struct message, list);
- if (recv_buf_size < msg->len) {
- spin_unlock_irqrestore(&mq->lock, flags);
- up(&mq->sem);
- return -EOVERFLOW;
- }
-
- /* consume the message */
- mq->recv_count--;
- memcpy(recv_buf, msg->buf, msg->len);
- *recv_len = msg->len;
-
- list_del(&msg->list);
-
- kfree(msg->buf);
- kfree(msg);
-
- spin_unlock_irqrestore(&mq->lock, flags);
-
- return 0;
-}
diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h
deleted file mode 100644
index 846a4840e..000000000
--- a/drivers/staging/wilc1000/wilc_msgqueue.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __WILC_MSG_QUEUE_H__
-#define __WILC_MSG_QUEUE_H__
-
-#include <linux/semaphore.h>
-#include <linux/list.h>
-
-struct message {
- void *buf;
- u32 len;
- struct list_head list;
-};
-
-struct message_queue {
- struct semaphore sem;
- spinlock_t lock;
- bool exiting;
- u32 recv_count;
- struct list_head msg_list;
-};
-
-int wilc_mq_create(struct message_queue *mq);
-int wilc_mq_send(struct message_queue *mq,
- const void *send_buf, u32 send_buf_size);
-int wilc_mq_recv(struct message_queue *mq,
- void *recv_buf, u32 recv_buf_size, u32 *recv_len);
-int wilc_mq_destroy(struct message_queue *mq);
-
-#endif
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
deleted file mode 100644
index 178645826..000000000
--- a/drivers/tty/serial/msm_serial.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Author: Robert Love <rlove@google.com>
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#ifndef __DRIVERS_SERIAL_MSM_SERIAL_H
-#define __DRIVERS_SERIAL_MSM_SERIAL_H
-
-#define UART_MR1 0x0000
-
-#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
-#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
-#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
-#define UART_MR1_RX_RDY_CTL BIT(7)
-#define UART_MR1_CTS_CTL BIT(6)
-
-#define UART_MR2 0x0004
-#define UART_MR2_ERROR_MODE BIT(6)
-#define UART_MR2_BITS_PER_CHAR 0x30
-#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
-#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
-#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
-#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
-#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
-#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
-#define UART_MR2_PARITY_MODE_NONE 0x0
-#define UART_MR2_PARITY_MODE_ODD 0x1
-#define UART_MR2_PARITY_MODE_EVEN 0x2
-#define UART_MR2_PARITY_MODE_SPACE 0x3
-#define UART_MR2_PARITY_MODE 0x3
-
-#define UART_CSR 0x0008
-
-#define UART_TF 0x000C
-#define UARTDM_TF 0x0070
-
-#define UART_CR 0x0010
-#define UART_CR_CMD_NULL (0 << 4)
-#define UART_CR_CMD_RESET_RX (1 << 4)
-#define UART_CR_CMD_RESET_TX (2 << 4)
-#define UART_CR_CMD_RESET_ERR (3 << 4)
-#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
-#define UART_CR_CMD_START_BREAK (5 << 4)
-#define UART_CR_CMD_STOP_BREAK (6 << 4)
-#define UART_CR_CMD_RESET_CTS (7 << 4)
-#define UART_CR_CMD_RESET_STALE_INT (8 << 4)
-#define UART_CR_CMD_PACKET_MODE (9 << 4)
-#define UART_CR_CMD_MODE_RESET (12 << 4)
-#define UART_CR_CMD_SET_RFR (13 << 4)
-#define UART_CR_CMD_RESET_RFR (14 << 4)
-#define UART_CR_CMD_PROTECTION_EN (16 << 4)
-#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
-#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
-#define UART_CR_CMD_FORCE_STALE (4 << 8)
-#define UART_CR_CMD_RESET_TX_READY (3 << 8)
-#define UART_CR_TX_DISABLE BIT(3)
-#define UART_CR_TX_ENABLE BIT(2)
-#define UART_CR_RX_DISABLE BIT(1)
-#define UART_CR_RX_ENABLE BIT(0)
-#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
-
-#define UART_IMR 0x0014
-#define UART_IMR_TXLEV BIT(0)
-#define UART_IMR_RXSTALE BIT(3)
-#define UART_IMR_RXLEV BIT(4)
-#define UART_IMR_DELTA_CTS BIT(5)
-#define UART_IMR_CURRENT_CTS BIT(6)
-#define UART_IMR_RXBREAK_START BIT(10)
-
-#define UART_IPR_RXSTALE_LAST 0x20
-#define UART_IPR_STALE_LSB 0x1F
-#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
-#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
-
-#define UART_IPR 0x0018
-#define UART_TFWR 0x001C
-#define UART_RFWR 0x0020
-#define UART_HCR 0x0024
-
-#define UART_MREG 0x0028
-#define UART_NREG 0x002C
-#define UART_DREG 0x0030
-#define UART_MNDREG 0x0034
-#define UART_IRDA 0x0038
-#define UART_MISR_MODE 0x0040
-#define UART_MISR_RESET 0x0044
-#define UART_MISR_EXPORT 0x0048
-#define UART_MISR_VAL 0x004C
-#define UART_TEST_CTRL 0x0050
-
-#define UART_SR 0x0008
-#define UART_SR_HUNT_CHAR BIT(7)
-#define UART_SR_RX_BREAK BIT(6)
-#define UART_SR_PAR_FRAME_ERR BIT(5)
-#define UART_SR_OVERRUN BIT(4)
-#define UART_SR_TX_EMPTY BIT(3)
-#define UART_SR_TX_READY BIT(2)
-#define UART_SR_RX_FULL BIT(1)
-#define UART_SR_RX_READY BIT(0)
-
-#define UART_RF 0x000C
-#define UARTDM_RF 0x0070
-#define UART_MISR 0x0010
-#define UART_ISR 0x0014
-#define UART_ISR_TX_READY BIT(7)
-
-#define UARTDM_RXFS 0x50
-#define UARTDM_RXFS_BUF_SHIFT 0x7
-#define UARTDM_RXFS_BUF_MASK 0x7
-
-#define UARTDM_DMEN 0x3C
-#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
-#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
-
-#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
-#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
-
-#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
-#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
-
-#define UARTDM_DMRX 0x34
-#define UARTDM_NCF_TX 0x40
-#define UARTDM_RX_TOTAL_SNAP 0x38
-
-#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
-
-static inline
-void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
-{
- writel_relaxed(val, port->membase + off);
-}
-
-static inline
-unsigned int msm_read(struct uart_port *port, unsigned int off)
-{
- return readl_relaxed(port->membase + off);
-}
-
-/*
- * Setup the MND registers to use the TCXO clock.
- */
-static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
-{
- msm_write(port, 0x06, UART_MREG);
- msm_write(port, 0xF1, UART_NREG);
- msm_write(port, 0x0F, UART_DREG);
- msm_write(port, 0x1A, UART_MNDREG);
- port->uartclk = 1843200;
-}
-
-/*
- * Setup the MND registers to use the TCXO clock divided by 4.
- */
-static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
-{
- msm_write(port, 0x18, UART_MREG);
- msm_write(port, 0xF6, UART_NREG);
- msm_write(port, 0x0F, UART_DREG);
- msm_write(port, 0x0A, UART_MNDREG);
- port->uartclk = 1843200;
-}
-
-static inline
-void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
-{
- if (port->uartclk == 19200000)
- msm_serial_set_mnd_regs_tcxo(port);
- else if (port->uartclk == 4800000)
- msm_serial_set_mnd_regs_tcxoby4(port);
-}
-
-#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
-
-#endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */
diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h
deleted file mode 100644
index 8826cca5f..000000000
--- a/drivers/usb/dwc3/platform_data.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * platform_data.h - USB DWC3 Platform Data Support
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- * Author: Felipe Balbi <balbi@ti.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 of
- * the License as published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/otg.h>
-
-struct dwc3_platform_data {
- enum usb_device_speed maximum_speed;
- enum usb_dr_mode dr_mode;
- bool usb3_lpm_capable;
-
- unsigned is_utmi_l1_suspend:1;
- u8 hird_threshold;
-
- u8 lpm_nyet_threshold;
-
- unsigned disable_scramble_quirk:1;
- unsigned has_lpm_erratum:1;
- unsigned u2exit_lfps_quirk:1;
- unsigned u2ss_inp3_quirk:1;
- unsigned req_p1p2p3_quirk:1;
- unsigned del_p1p2p3_quirk:1;
- unsigned del_phy_power_chg_quirk:1;
- unsigned lfps_filter_quirk:1;
- unsigned rx_detect_poll_quirk:1;
- unsigned dis_u3_susphy_quirk:1;
- unsigned dis_u2_susphy_quirk:1;
- unsigned dis_enblslpm_quirk:1;
- unsigned dis_rxdet_inp3_quirk:1;
-
- unsigned tx_de_emphasis_quirk:1;
- unsigned tx_de_emphasis:2;
-
- u32 fladj_value;
-
- const char *hsphy_interface;
-};
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
deleted file mode 100644
index bd4695075..000000000
--- a/drivers/usb/gadget/udc/udc-core.c
+++ /dev/null
@@ -1,800 +0,0 @@
-/**
- * udc.c - Core UDC Framework
- *
- * Copyright (C) 2010 Texas Instruments
- * Author: Felipe Balbi <balbi@ti.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 of
- * the License as published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/err.h>
-#include <linux/dma-mapping.h>
-#include <linux/workqueue.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb.h>
-
-/**
- * struct usb_udc - describes one usb device controller
- * @driver - the gadget driver pointer. For use by the class code
- * @dev - the child device to the actual controller
- * @gadget - the gadget. For use by the class code
- * @list - for use by the udc class driver
- * @vbus - for udcs who care about vbus status, this value is real vbus status;
- * for udcs who do not care about vbus status, this value is always true
- *
- * This represents the internal data structure which is used by the UDC-class
- * to hold information about udc driver and gadget together.
- */
-struct usb_udc {
- struct usb_gadget_driver *driver;
- struct usb_gadget *gadget;
- struct device dev;
- struct list_head list;
- bool vbus;
-};
-
-static struct class *udc_class;
-static LIST_HEAD(udc_list);
-static LIST_HEAD(gadget_driver_pending_list);
-static DEFINE_MUTEX(udc_lock);
-
-static int udc_bind_to_driver(struct usb_udc *udc,
- struct usb_gadget_driver *driver);
-
-/* ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_HAS_DMA
-
-int usb_gadget_map_request_by_dev(struct device *dev,
- struct usb_request *req, int is_in)
-{
- if (req->length == 0)
- return 0;
-
- if (req->num_sgs) {
- int mapped;
-
- mapped = dma_map_sg(dev, req->sg, req->num_sgs,
- is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- if (mapped == 0) {
- dev_err(dev, "failed to map SGs\n");
- return -EFAULT;
- }
-
- req->num_mapped_sgs = mapped;
- } else {
- req->dma = dma_map_single(dev, req->buf, req->length,
- is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
- if (dma_mapping_error(dev, req->dma)) {
- dev_err(dev, "failed to map buffer\n");
- return -EFAULT;
- }
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_gadget_map_request_by_dev);
-
-int usb_gadget_map_request(struct usb_gadget *gadget,
- struct usb_request *req, int is_in)
-{
- return usb_gadget_map_request_by_dev(gadget->dev.parent, req, is_in);
-}
-EXPORT_SYMBOL_GPL(usb_gadget_map_request);
-
-void usb_gadget_unmap_request_by_dev(struct device *dev,
- struct usb_request *req, int is_in)
-{
- if (req->length == 0)
- return;
-
- if (req->num_mapped_sgs) {
- dma_unmap_sg(dev, req->sg, req->num_sgs,
- is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
- req->num_mapped_sgs = 0;
- } else {
- dma_unmap_single(dev, req->dma, req->length,
- is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- }
-}
-EXPORT_SYMBOL_GPL(usb_gadget_unmap_request_by_dev);
-
-void usb_gadget_unmap_request(struct usb_gadget *gadget,
- struct usb_request *req, int is_in)
-{
- usb_gadget_unmap_request_by_dev(gadget->dev.parent, req, is_in);
-}
-EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
-
-#endif /* CONFIG_HAS_DMA */
-
-/* ------------------------------------------------------------------------- */
-
-/**
- * usb_gadget_giveback_request - give the request back to the gadget layer
- * Context: in_interrupt()
- *
- * This is called by device controller drivers in order to return the
- * completed request back to the gadget layer.
- */
-void usb_gadget_giveback_request(struct usb_ep *ep,
- struct usb_request *req)
-{
- if (likely(req->status == 0))
- usb_led_activity(USB_LED_EVENT_GADGET);
-
- req->complete(ep, req);
-}
-EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
-
-/* ------------------------------------------------------------------------- */
-
-/**
- * gadget_find_ep_by_name - returns ep whose name is the same as sting passed
- * in second parameter or NULL if searched endpoint not found
- * @g: controller to check for quirk
- * @name: name of searched endpoint
- */
-struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, const char *name)
-{
- struct usb_ep *ep;
-
- gadget_for_each_ep(ep, g) {
- if (!strcmp(ep->name, name))
- return ep;
- }
-
- return NULL;
-}
-EXPORT_SYMBOL_GPL(gadget_find_ep_by_name);
-
-/* ------------------------------------------------------------------------- */
-
-int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
- struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
- struct usb_ss_ep_comp_descriptor *ep_comp)
-{
- u8 type;
- u16 max;
- int num_req_streams = 0;
-
- /* endpoint already claimed? */
- if (ep->claimed)
- return 0;
-
- type = usb_endpoint_type(desc);
- max = 0x7ff & usb_endpoint_maxp(desc);
-
- if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
- return 0;
- if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
- return 0;
-
- if (max > ep->maxpacket_limit)
- return 0;
-
- /* "high bandwidth" works only at high speed */
- if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11))
- return 0;
-
- switch (type) {
- case USB_ENDPOINT_XFER_CONTROL:
- /* only support ep0 for portable CONTROL traffic */
- return 0;
- case USB_ENDPOINT_XFER_ISOC:
- if (!ep->caps.type_iso)
- return 0;
- /* ISO: limit 1023 bytes full speed, 1024 high/super speed */
- if (!gadget_is_dualspeed(gadget) && max > 1023)
- return 0;
- break;
- case USB_ENDPOINT_XFER_BULK:
- if (!ep->caps.type_bulk)
- return 0;
- if (ep_comp && gadget_is_superspeed(gadget)) {
- /* Get the number of required streams from the
- * EP companion descriptor and see if the EP
- * matches it
- */
- num_req_streams = ep_comp->bmAttributes & 0x1f;
- if (num_req_streams > ep->max_streams)
- return 0;
- }
- break;
- case USB_ENDPOINT_XFER_INT:
- /* Bulk endpoints handle interrupt transfers,
- * except the toggle-quirky iso-synch kind
- */
- if (!ep->caps.type_int && !ep->caps.type_bulk)
- return 0;
- /* INT: limit 64 bytes full speed, 1024 high/super speed */
- if (!gadget_is_dualspeed(gadget) && max > 64)
- return 0;
- break;
- }
-
- return 1;
-}
-EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
-
-/* ------------------------------------------------------------------------- */
-
-static void usb_gadget_state_work(struct work_struct *work)
-{
- struct usb_gadget *gadget = work_to_gadget(work);
- struct usb_udc *udc = gadget->udc;
-
- if (udc)
- sysfs_notify(&udc->dev.kobj, NULL, "state");
-}
-
-void usb_gadget_set_state(struct usb_gadget *gadget,
- enum usb_device_state state)
-{
- gadget->state = state;
- schedule_work(&gadget->work);
-}
-EXPORT_SYMBOL_GPL(usb_gadget_set_state);
-
-/* ------------------------------------------------------------------------- */
-
-static void usb_udc_connect_control(struct usb_udc *udc)
-{
- if (udc->vbus)
- usb_gadget_connect(udc->gadget);
- else
- usb_gadget_disconnect(udc->gadget);
-}
-
-/**
- * usb_udc_vbus_handler - updates the udc core vbus status, and try to
- * connect or disconnect gadget
- * @gadget: The gadget which vbus change occurs
- * @status: The vbus status
- *
- * The udc driver calls it when it wants to connect or disconnect gadget
- * according to vbus status.
- */
-void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status)
-{
- struct usb_udc *udc = gadget->udc;
-
- if (udc) {
- udc->vbus = status;
- usb_udc_connect_control(udc);
- }
-}
-EXPORT_SYMBOL_GPL(usb_udc_vbus_handler);
-
-/**
- * usb_gadget_udc_reset - notifies the udc core that bus reset occurs
- * @gadget: The gadget which bus reset occurs
- * @driver: The gadget driver we want to notify
- *
- * If the udc driver has bus reset handler, it needs to call this when the bus
- * reset occurs, it notifies the gadget driver that the bus reset occurs as
- * well as updates gadget state.
- */
-void usb_gadget_udc_reset(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
-{
- driver->reset(gadget);
- usb_gadget_set_state(gadget, USB_STATE_DEFAULT);
-}
-EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
-
-/**
- * usb_gadget_udc_start - tells usb device controller to start up
- * @udc: The UDC to be started
- *
- * This call is issued by the UDC Class driver when it's about
- * to register a gadget driver to the device controller, before
- * calling gadget driver's bind() method.
- *
- * It allows the controller to be powered off until strictly
- * necessary to have it powered on.
- *
- * Returns zero on success, else negative errno.
- */
-static inline int usb_gadget_udc_start(struct usb_udc *udc)
-{
- return udc->gadget->ops->udc_start(udc->gadget, udc->driver);
-}
-
-/**
- * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
- * @gadget: The device we want to stop activity
- * @driver: The driver to unbind from @gadget
- *
- * This call is issued by the UDC Class driver after calling
- * gadget driver's unbind() method.
- *
- * The details are implementation specific, but it can go as
- * far as powering off UDC completely and disable its data
- * line pullups.
- */
-static inline void usb_gadget_udc_stop(struct usb_udc *udc)
-{
- udc->gadget->ops->udc_stop(udc->gadget);
-}
-
-/**
- * usb_udc_release - release the usb_udc struct
- * @dev: the dev member within usb_udc
- *
- * This is called by driver's core in order to free memory once the last
- * reference is released.
- */
-static void usb_udc_release(struct device *dev)
-{
- struct usb_udc *udc;
-
- udc = container_of(dev, struct usb_udc, dev);
- dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
- kfree(udc);
-}
-
-static const struct attribute_group *usb_udc_attr_groups[];
-
-static void usb_udc_nop_release(struct device *dev)
-{
- dev_vdbg(dev, "%s\n", __func__);
-}
-
-/**
- * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
- * @parent: the parent device to this udc. Usually the controller driver's
- * device.
- * @gadget: the gadget to be added to the list.
- * @release: a gadget release function.
- *
- * Returns zero on success, negative errno otherwise.
- */
-int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
- void (*release)(struct device *dev))
-{
- struct usb_udc *udc;
- struct usb_gadget_driver *driver;
- int ret = -ENOMEM;
-
- udc = kzalloc(sizeof(*udc), GFP_KERNEL);
- if (!udc)
- goto err1;
-
- dev_set_name(&gadget->dev, "gadget");
- INIT_WORK(&gadget->work, usb_gadget_state_work);
- gadget->dev.parent = parent;
-
- if (release)
- gadget->dev.release = release;
- else
- gadget->dev.release = usb_udc_nop_release;
-
- ret = device_register(&gadget->dev);
- if (ret)
- goto err2;
-
- device_initialize(&udc->dev);
- udc->dev.release = usb_udc_release;
- udc->dev.class = udc_class;
- udc->dev.groups = usb_udc_attr_groups;
- udc->dev.parent = parent;
- ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
- if (ret)
- goto err3;
-
- udc->gadget = gadget;
- gadget->udc = udc;
-
- mutex_lock(&udc_lock);
- list_add_tail(&udc->list, &udc_list);
-
- ret = device_add(&udc->dev);
- if (ret)
- goto err4;
-
- usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
- udc->vbus = true;
-
- /* pick up one of pending gadget drivers */
- list_for_each_entry(driver, &gadget_driver_pending_list, pending) {
- if (!driver->udc_name || strcmp(driver->udc_name,
- dev_name(&udc->dev)) == 0) {
- ret = udc_bind_to_driver(udc, driver);
- if (ret != -EPROBE_DEFER)
- list_del(&driver->pending);
- if (ret)
- goto err4;
- break;
- }
- }
-
- mutex_unlock(&udc_lock);
-
- return 0;
-
-err4:
- list_del(&udc->list);
- mutex_unlock(&udc_lock);
-
-err3:
- put_device(&udc->dev);
- device_del(&gadget->dev);
-
-err2:
- put_device(&gadget->dev);
- kfree(udc);
-
-err1:
- return ret;
-}
-EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
-
-/**
- * usb_get_gadget_udc_name - get the name of the first UDC controller
- * This functions returns the name of the first UDC controller in the system.
- * Please note that this interface is usefull only for legacy drivers which
- * assume that there is only one UDC controller in the system and they need to
- * get its name before initialization. There is no guarantee that the UDC
- * of the returned name will be still available, when gadget driver registers
- * itself.
- *
- * Returns pointer to string with UDC controller name on success, NULL
- * otherwise. Caller should kfree() returned string.
- */
-char *usb_get_gadget_udc_name(void)
-{
- struct usb_udc *udc;
- char *name = NULL;
-
- /* For now we take the first available UDC */
- mutex_lock(&udc_lock);
- list_for_each_entry(udc, &udc_list, list) {
- if (!udc->driver) {
- name = kstrdup(udc->gadget->name, GFP_KERNEL);
- break;
- }
- }
- mutex_unlock(&udc_lock);
- return name;
-}
-EXPORT_SYMBOL_GPL(usb_get_gadget_udc_name);
-
-/**
- * usb_add_gadget_udc - adds a new gadget to the udc class driver list
- * @parent: the parent device to this udc. Usually the controller
- * driver's device.
- * @gadget: the gadget to be added to the list
- *
- * Returns zero on success, negative errno otherwise.
- */
-int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
-{
- return usb_add_gadget_udc_release(parent, gadget, NULL);
-}
-EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
-
-static void usb_gadget_remove_driver(struct usb_udc *udc)
-{
- dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
- udc->driver->function);
-
- kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
-
- usb_gadget_disconnect(udc->gadget);
- udc->driver->disconnect(udc->gadget);
- udc->driver->unbind(udc->gadget);
- usb_gadget_udc_stop(udc);
-
- udc->driver = NULL;
- udc->dev.driver = NULL;
- udc->gadget->dev.driver = NULL;
-}
-
-/**
- * usb_del_gadget_udc - deletes @udc from udc_list
- * @gadget: the gadget to be removed.
- *
- * This, will call usb_gadget_unregister_driver() if
- * the @udc is still busy.
- */
-void usb_del_gadget_udc(struct usb_gadget *gadget)
-{
- struct usb_udc *udc = gadget->udc;
-
- if (!udc)
- return;
-
- dev_vdbg(gadget->dev.parent, "unregistering gadget\n");
-
- mutex_lock(&udc_lock);
- list_del(&udc->list);
-
- if (udc->driver) {
- struct usb_gadget_driver *driver = udc->driver;
-
- usb_gadget_remove_driver(udc);
- list_add(&driver->pending, &gadget_driver_pending_list);
- }
- mutex_unlock(&udc_lock);
-
- kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
- flush_work(&gadget->work);
- device_unregister(&udc->dev);
- device_unregister(&gadget->dev);
-}
-EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
-
-/* ------------------------------------------------------------------------- */
-
-static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
-{
- int ret;
-
- dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
- driver->function);
-
- udc->driver = driver;
- udc->dev.driver = &driver->driver;
- udc->gadget->dev.driver = &driver->driver;
-
- ret = driver->bind(udc->gadget, driver);
- if (ret)
- goto err1;
- ret = usb_gadget_udc_start(udc);
- if (ret) {
- driver->unbind(udc->gadget);
- goto err1;
- }
- usb_udc_connect_control(udc);
-
- kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
- return 0;
-err1:
- if (ret != -EISNAM)
- dev_err(&udc->dev, "failed to start %s: %d\n",
- udc->driver->function, ret);
- udc->driver = NULL;
- udc->dev.driver = NULL;
- udc->gadget->dev.driver = NULL;
- return ret;
-}
-
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
-{
- struct usb_udc *udc = NULL;
- int ret = -ENODEV;
-
- if (!driver || !driver->bind || !driver->setup)
- return -EINVAL;
-
- mutex_lock(&udc_lock);
- if (driver->udc_name) {
- list_for_each_entry(udc, &udc_list, list) {
- ret = strcmp(driver->udc_name, dev_name(&udc->dev));
- if (!ret)
- break;
- }
- if (!ret && !udc->driver)
- goto found;
- } else {
- list_for_each_entry(udc, &udc_list, list) {
- /* For now we take the first one */
- if (!udc->driver)
- goto found;
- }
- }
-
- if (!driver->match_existing_only) {
- list_add_tail(&driver->pending, &gadget_driver_pending_list);
- pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",
- driver->function);
- ret = 0;
- }
-
- mutex_unlock(&udc_lock);
- return ret;
-found:
- ret = udc_bind_to_driver(udc, driver);
- mutex_unlock(&udc_lock);
- return ret;
-}
-EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);
-
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-{
- struct usb_udc *udc = NULL;
- int ret = -ENODEV;
-
- if (!driver || !driver->unbind)
- return -EINVAL;
-
- mutex_lock(&udc_lock);
- list_for_each_entry(udc, &udc_list, list)
- if (udc->driver == driver) {
- usb_gadget_remove_driver(udc);
- usb_gadget_set_state(udc->gadget,
- USB_STATE_NOTATTACHED);
- ret = 0;
- break;
- }
-
- if (ret) {
- list_del(&driver->pending);
- ret = 0;
- }
- mutex_unlock(&udc_lock);
- return ret;
-}
-EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
-
-/* ------------------------------------------------------------------------- */
-
-static ssize_t usb_udc_srp_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t n)
-{
- struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
-
- if (sysfs_streq(buf, "1"))
- usb_gadget_wakeup(udc->gadget);
-
- return n;
-}
-static DEVICE_ATTR(srp, S_IWUSR, NULL, usb_udc_srp_store);
-
-static ssize_t usb_udc_softconn_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t n)
-{
- struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
-
- if (!udc->driver) {
- dev_err(dev, "soft-connect without a gadget driver\n");
- return -EOPNOTSUPP;
- }
-
- if (sysfs_streq(buf, "connect")) {
- usb_gadget_udc_start(udc);
- usb_gadget_connect(udc->gadget);
- } else if (sysfs_streq(buf, "disconnect")) {
- usb_gadget_disconnect(udc->gadget);
- udc->driver->disconnect(udc->gadget);
- usb_gadget_udc_stop(udc);
- } else {
- dev_err(dev, "unsupported command '%s'\n", buf);
- return -EINVAL;
- }
-
- return n;
-}
-static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
-
-static ssize_t state_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
- struct usb_gadget *gadget = udc->gadget;
-
- return sprintf(buf, "%s\n", usb_state_string(gadget->state));
-}
-static DEVICE_ATTR_RO(state);
-
-#define USB_UDC_SPEED_ATTR(name, param) \
-ssize_t name##_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- struct usb_udc *udc = container_of(dev, struct usb_udc, dev); \
- return snprintf(buf, PAGE_SIZE, "%s\n", \
- usb_speed_string(udc->gadget->param)); \
-} \
-static DEVICE_ATTR_RO(name)
-
-static USB_UDC_SPEED_ATTR(current_speed, speed);
-static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
-
-#define USB_UDC_ATTR(name) \
-ssize_t name##_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- struct usb_udc *udc = container_of(dev, struct usb_udc, dev); \
- struct usb_gadget *gadget = udc->gadget; \
- \
- return snprintf(buf, PAGE_SIZE, "%d\n", gadget->name); \
-} \
-static DEVICE_ATTR_RO(name)
-
-static USB_UDC_ATTR(is_otg);
-static USB_UDC_ATTR(is_a_peripheral);
-static USB_UDC_ATTR(b_hnp_enable);
-static USB_UDC_ATTR(a_hnp_support);
-static USB_UDC_ATTR(a_alt_hnp_support);
-static USB_UDC_ATTR(is_selfpowered);
-
-static struct attribute *usb_udc_attrs[] = {
- &dev_attr_srp.attr,
- &dev_attr_soft_connect.attr,
- &dev_attr_state.attr,
- &dev_attr_current_speed.attr,
- &dev_attr_maximum_speed.attr,
-
- &dev_attr_is_otg.attr,
- &dev_attr_is_a_peripheral.attr,
- &dev_attr_b_hnp_enable.attr,
- &dev_attr_a_hnp_support.attr,
- &dev_attr_a_alt_hnp_support.attr,
- &dev_attr_is_selfpowered.attr,
- NULL,
-};
-
-static const struct attribute_group usb_udc_attr_group = {
- .attrs = usb_udc_attrs,
-};
-
-static const struct attribute_group *usb_udc_attr_groups[] = {
- &usb_udc_attr_group,
- NULL,
-};
-
-static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
- int ret;
-
- ret = add_uevent_var(env, "USB_UDC_NAME=%s", udc->gadget->name);
- if (ret) {
- dev_err(dev, "failed to add uevent USB_UDC_NAME\n");
- return ret;
- }
-
- if (udc->driver) {
- ret = add_uevent_var(env, "USB_UDC_DRIVER=%s",
- udc->driver->function);
- if (ret) {
- dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n");
- return ret;
- }
- }
-
- return 0;
-}
-
-static int __init usb_udc_init(void)
-{
- udc_class = class_create(THIS_MODULE, "udc");
- if (IS_ERR(udc_class)) {
- pr_err("failed to create udc class --> %ld\n",
- PTR_ERR(udc_class));
- return PTR_ERR(udc_class);
- }
-
- udc_class->dev_uevent = usb_udc_uevent;
- return 0;
-}
-subsys_initcall(usb_udc_init);
-
-static void __exit usb_udc_exit(void)
-{
- class_destroy(udc_class);
-}
-module_exit(usb_udc_exit);
-
-MODULE_DESCRIPTION("UDC Framework");
-MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
deleted file mode 100644
index bdef0d6eb..000000000
--- a/drivers/usb/misc/usbled.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * USB LED driver
- *
- * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
- *
- * 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, version 2.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-
-
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
-#define DRIVER_DESC "USB LED Driver"
-
-enum led_type {
- DELCOM_VISUAL_SIGNAL_INDICATOR,
- DREAM_CHEEKY_WEBMAIL_NOTIFIER,
- RISO_KAGAKU_LED
-};
-
-/* the Webmail LED made by RISO KAGAKU CORP. decodes a color index
- internally, we want to keep the red+green+blue sysfs api, so we decode
- from 1-bit RGB to the riso kagaku color index according to this table... */
-
-static unsigned const char riso_kagaku_tbl[] = {
-/* R+2G+4B -> riso kagaku color index */
- [0] = 0, /* black */
- [1] = 2, /* red */
- [2] = 1, /* green */
- [3] = 5, /* yellow */
- [4] = 3, /* blue */
- [5] = 6, /* magenta */
- [6] = 4, /* cyan */
- [7] = 7 /* white */
-};
-
-#define RISO_KAGAKU_IX(r,g,b) riso_kagaku_tbl[((r)?1:0)+((g)?2:0)+((b)?4:0)]
-
-/* table of devices that work with this driver */
-static const struct usb_device_id id_table[] = {
- { USB_DEVICE(0x0fc5, 0x1223),
- .driver_info = DELCOM_VISUAL_SIGNAL_INDICATOR },
- { USB_DEVICE(0x1d34, 0x0004),
- .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },
- { USB_DEVICE(0x1d34, 0x000a),
- .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },
- { USB_DEVICE(0x1294, 0x1320),
- .driver_info = RISO_KAGAKU_LED },
- { },
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-struct usb_led {
- struct usb_device *udev;
- unsigned char blue;
- unsigned char red;
- unsigned char green;
- enum led_type type;
-};
-
-static void change_color(struct usb_led *led)
-{
- int retval = 0;
- unsigned char *buffer;
- int actlength;
-
- buffer = kmalloc(8, GFP_KERNEL);
- if (!buffer) {
- dev_err(&led->udev->dev, "out of memory\n");
- return;
- }
-
- switch (led->type) {
- case DELCOM_VISUAL_SIGNAL_INDICATOR: {
- unsigned char color = 0x07;
-
- if (led->blue)
- color &= ~0x04;
- if (led->red)
- color &= ~0x02;
- if (led->green)
- color &= ~0x01;
- dev_dbg(&led->udev->dev,
- "blue = %d, red = %d, green = %d, color = %.2x\n",
- led->blue, led->red, led->green, color);
-
- retval = usb_control_msg(led->udev,
- usb_sndctrlpipe(led->udev, 0),
- 0x12,
- 0xc8,
- (0x02 * 0x100) + 0x0a,
- (0x00 * 0x100) + color,
- buffer,
- 8,
- 2000);
- break;
- }
-
- case DREAM_CHEEKY_WEBMAIL_NOTIFIER:
- dev_dbg(&led->udev->dev,
- "red = %d, green = %d, blue = %d\n",
- led->red, led->green, led->blue);
-
- buffer[0] = led->red;
- buffer[1] = led->green;
- buffer[2] = led->blue;
- buffer[3] = buffer[4] = buffer[5] = 0;
- buffer[6] = 0x1a;
- buffer[7] = 0x05;
-
- retval = usb_control_msg(led->udev,
- usb_sndctrlpipe(led->udev, 0),
- 0x09,
- 0x21,
- 0x200,
- 0,
- buffer,
- 8,
- 2000);
- break;
-
- case RISO_KAGAKU_LED:
- buffer[0] = RISO_KAGAKU_IX(led->red, led->green, led->blue);
- buffer[1] = 0;
- buffer[2] = 0;
- buffer[3] = 0;
- buffer[4] = 0;
-
- retval = usb_interrupt_msg(led->udev,
- usb_sndctrlpipe(led->udev, 2),
- buffer, 5, &actlength, 1000 /*ms timeout*/);
- break;
-
- default:
- dev_err(&led->udev->dev, "unknown device type %d\n", led->type);
- }
-
- if (retval)
- dev_dbg(&led->udev->dev, "retval = %d\n", retval);
- kfree(buffer);
-}
-
-#define show_set(value) \
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr,\
- char *buf) \
-{ \
- struct usb_interface *intf = to_usb_interface(dev); \
- struct usb_led *led = usb_get_intfdata(intf); \
- \
- return sprintf(buf, "%d\n", led->value); \
-} \
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr,\
- const char *buf, size_t count) \
-{ \
- struct usb_interface *intf = to_usb_interface(dev); \
- struct usb_led *led = usb_get_intfdata(intf); \
- int temp = simple_strtoul(buf, NULL, 10); \
- \
- led->value = temp; \
- change_color(led); \
- return count; \
-} \
-static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, show_##value, set_##value);
-show_set(blue);
-show_set(red);
-show_set(green);
-
-static int led_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
-{
- struct usb_device *udev = interface_to_usbdev(interface);
- struct usb_led *dev = NULL;
- int retval = -ENOMEM;
-
- dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL);
- if (dev == NULL) {
- dev_err(&interface->dev, "out of memory\n");
- goto error_mem;
- }
-
- dev->udev = usb_get_dev(udev);
- dev->type = id->driver_info;
-
- usb_set_intfdata(interface, dev);
-
- retval = device_create_file(&interface->dev, &dev_attr_blue);
- if (retval)
- goto error;
- retval = device_create_file(&interface->dev, &dev_attr_red);
- if (retval)
- goto error;
- retval = device_create_file(&interface->dev, &dev_attr_green);
- if (retval)
- goto error;
-
- if (dev->type == DREAM_CHEEKY_WEBMAIL_NOTIFIER) {
- unsigned char *enable;
-
- enable = kmemdup("\x1f\x02\0\x5f\0\0\x1a\x03", 8, GFP_KERNEL);
- if (!enable) {
- dev_err(&interface->dev, "out of memory\n");
- retval = -ENOMEM;
- goto error;
- }
-
- retval = usb_control_msg(udev,
- usb_sndctrlpipe(udev, 0),
- 0x09,
- 0x21,
- 0x200,
- 0,
- enable,
- 8,
- 2000);
-
- kfree(enable);
- if (retval != 8)
- goto error;
- }
-
- dev_info(&interface->dev, "USB LED device now attached\n");
- return 0;
-
-error:
- device_remove_file(&interface->dev, &dev_attr_blue);
- device_remove_file(&interface->dev, &dev_attr_red);
- device_remove_file(&interface->dev, &dev_attr_green);
- usb_set_intfdata(interface, NULL);
- usb_put_dev(dev->udev);
- kfree(dev);
-error_mem:
- return retval;
-}
-
-static void led_disconnect(struct usb_interface *interface)
-{
- struct usb_led *dev;
-
- dev = usb_get_intfdata(interface);
-
- device_remove_file(&interface->dev, &dev_attr_blue);
- device_remove_file(&interface->dev, &dev_attr_red);
- device_remove_file(&interface->dev, &dev_attr_green);
-
- /* first remove the files, then set the pointer to NULL */
- usb_set_intfdata(interface, NULL);
-
- usb_put_dev(dev->udev);
-
- kfree(dev);
-
- dev_info(&interface->dev, "USB LED now disconnected\n");
-}
-
-static struct usb_driver led_driver = {
- .name = "usbled",
- .probe = led_probe,
- .disconnect = led_disconnect,
- .id_table = id_table,
-};
-
-module_usb_driver(led_driver);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
deleted file mode 100644
index bbfd3a184..000000000
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/* vi: ts=8 sw=8
- *
- * TI 3410/5052 USB Serial Driver Header
- *
- * Copyright (C) 2004 Texas Instruments
- *
- * This driver is based on the Linux io_ti driver, which is
- * Copyright (C) 2000-2002 Inside Out Networks
- * Copyright (C) 2001-2002 Greg Kroah-Hartman
- *
- * 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.
- *
- * For questions or problems with this driver, contact Texas Instruments
- * technical support, or Al Borchers <alborchers@steinerpoint.com>, or
- * Peter Berger <pberger@brimson.com>.
- */
-
-#ifndef _TI_3410_5052_H_
-#define _TI_3410_5052_H_
-
-/* Configuration ids */
-#define TI_BOOT_CONFIG 1
-#define TI_ACTIVE_CONFIG 2
-
-/* Vendor and product ids */
-#define TI_VENDOR_ID 0x0451
-#define IBM_VENDOR_ID 0x04b3
-#define TI_3410_PRODUCT_ID 0x3410
-#define IBM_4543_PRODUCT_ID 0x4543
-#define IBM_454B_PRODUCT_ID 0x454b
-#define IBM_454C_PRODUCT_ID 0x454c
-#define TI_3410_EZ430_ID 0xF430 /* TI ez430 development tool */
-#define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */
-#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
-#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
-#define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */
-#define FRI2_PRODUCT_ID 0x5053 /* Fish River Island II */
-
-/* Multi-Tech vendor and product ids */
-#define MTS_VENDOR_ID 0x06E0
-#define MTS_GSM_NO_FW_PRODUCT_ID 0xF108
-#define MTS_CDMA_NO_FW_PRODUCT_ID 0xF109
-#define MTS_CDMA_PRODUCT_ID 0xF110
-#define MTS_GSM_PRODUCT_ID 0xF111
-#define MTS_EDGE_PRODUCT_ID 0xF112
-#define MTS_MT9234MU_PRODUCT_ID 0xF114
-#define MTS_MT9234ZBA_PRODUCT_ID 0xF115
-#define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319
-
-/* Abbott Diabetics vendor and product ids */
-#define ABBOTT_VENDOR_ID 0x1a61
-#define ABBOTT_STEREO_PLUG_ID 0x3410
-#define ABBOTT_PRODUCT_ID ABBOTT_STEREO_PLUG_ID
-#define ABBOTT_STRIP_PORT_ID 0x3420
-
-/* Honeywell vendor and product IDs */
-#define HONEYWELL_VENDOR_ID 0x10ac
-#define HONEYWELL_HGI80_PRODUCT_ID 0x0102 /* Honeywell HGI80 */
-
-/* Moxa UPORT 11x0 vendor and product IDs */
-#define MXU1_VENDOR_ID 0x110a
-#define MXU1_1110_PRODUCT_ID 0x1110
-#define MXU1_1130_PRODUCT_ID 0x1130
-#define MXU1_1131_PRODUCT_ID 0x1131
-#define MXU1_1150_PRODUCT_ID 0x1150
-#define MXU1_1151_PRODUCT_ID 0x1151
-
-/* Commands */
-#define TI_GET_VERSION 0x01
-#define TI_GET_PORT_STATUS 0x02
-#define TI_GET_PORT_DEV_INFO 0x03
-#define TI_GET_CONFIG 0x04
-#define TI_SET_CONFIG 0x05
-#define TI_OPEN_PORT 0x06
-#define TI_CLOSE_PORT 0x07
-#define TI_START_PORT 0x08
-#define TI_STOP_PORT 0x09
-#define TI_TEST_PORT 0x0A
-#define TI_PURGE_PORT 0x0B
-#define TI_RESET_EXT_DEVICE 0x0C
-#define TI_WRITE_DATA 0x80
-#define TI_READ_DATA 0x81
-#define TI_REQ_TYPE_CLASS 0x82
-
-/* Module identifiers */
-#define TI_I2C_PORT 0x01
-#define TI_IEEE1284_PORT 0x02
-#define TI_UART1_PORT 0x03
-#define TI_UART2_PORT 0x04
-#define TI_RAM_PORT 0x05
-
-/* Modem status */
-#define TI_MSR_DELTA_CTS 0x01
-#define TI_MSR_DELTA_DSR 0x02
-#define TI_MSR_DELTA_RI 0x04
-#define TI_MSR_DELTA_CD 0x08
-#define TI_MSR_CTS 0x10
-#define TI_MSR_DSR 0x20
-#define TI_MSR_RI 0x40
-#define TI_MSR_CD 0x80
-#define TI_MSR_DELTA_MASK 0x0F
-#define TI_MSR_MASK 0xF0
-
-/* Line status */
-#define TI_LSR_OVERRUN_ERROR 0x01
-#define TI_LSR_PARITY_ERROR 0x02
-#define TI_LSR_FRAMING_ERROR 0x04
-#define TI_LSR_BREAK 0x08
-#define TI_LSR_ERROR 0x0F
-#define TI_LSR_RX_FULL 0x10
-#define TI_LSR_TX_EMPTY 0x20
-
-/* Line control */
-#define TI_LCR_BREAK 0x40
-
-/* Modem control */
-#define TI_MCR_LOOP 0x04
-#define TI_MCR_DTR 0x10
-#define TI_MCR_RTS 0x20
-
-/* Mask settings */
-#define TI_UART_ENABLE_RTS_IN 0x0001
-#define TI_UART_DISABLE_RTS 0x0002
-#define TI_UART_ENABLE_PARITY_CHECKING 0x0008
-#define TI_UART_ENABLE_DSR_OUT 0x0010
-#define TI_UART_ENABLE_CTS_OUT 0x0020
-#define TI_UART_ENABLE_X_OUT 0x0040
-#define TI_UART_ENABLE_XA_OUT 0x0080
-#define TI_UART_ENABLE_X_IN 0x0100
-#define TI_UART_ENABLE_DTR_IN 0x0800
-#define TI_UART_DISABLE_DTR 0x1000
-#define TI_UART_ENABLE_MS_INTS 0x2000
-#define TI_UART_ENABLE_AUTO_START_DMA 0x4000
-
-/* Parity */
-#define TI_UART_NO_PARITY 0x00
-#define TI_UART_ODD_PARITY 0x01
-#define TI_UART_EVEN_PARITY 0x02
-#define TI_UART_MARK_PARITY 0x03
-#define TI_UART_SPACE_PARITY 0x04
-
-/* Stop bits */
-#define TI_UART_1_STOP_BITS 0x00
-#define TI_UART_1_5_STOP_BITS 0x01
-#define TI_UART_2_STOP_BITS 0x02
-
-/* Bits per character */
-#define TI_UART_5_DATA_BITS 0x00
-#define TI_UART_6_DATA_BITS 0x01
-#define TI_UART_7_DATA_BITS 0x02
-#define TI_UART_8_DATA_BITS 0x03
-
-/* 232/485 modes */
-#define TI_UART_232 0x00
-#define TI_UART_485_RECEIVER_DISABLED 0x01
-#define TI_UART_485_RECEIVER_ENABLED 0x02
-
-/* Pipe transfer mode and timeout */
-#define TI_PIPE_MODE_CONTINOUS 0x01
-#define TI_PIPE_MODE_MASK 0x03
-#define TI_PIPE_TIMEOUT_MASK 0x7C
-#define TI_PIPE_TIMEOUT_ENABLE 0x80
-
-/* Config struct */
-struct ti_uart_config {
- __u16 wBaudRate;
- __u16 wFlags;
- __u8 bDataBits;
- __u8 bParity;
- __u8 bStopBits;
- char cXon;
- char cXoff;
- __u8 bUartMode;
-} __attribute__((packed));
-
-/* Get port status */
-struct ti_port_status {
- __u8 bCmdCode;
- __u8 bModuleId;
- __u8 bErrorCode;
- __u8 bMSR;
- __u8 bLSR;
-} __attribute__((packed));
-
-/* Purge modes */
-#define TI_PURGE_OUTPUT 0x00
-#define TI_PURGE_INPUT 0x80
-
-/* Read/Write data */
-#define TI_RW_DATA_ADDR_SFR 0x10
-#define TI_RW_DATA_ADDR_IDATA 0x20
-#define TI_RW_DATA_ADDR_XDATA 0x30
-#define TI_RW_DATA_ADDR_CODE 0x40
-#define TI_RW_DATA_ADDR_GPIO 0x50
-#define TI_RW_DATA_ADDR_I2C 0x60
-#define TI_RW_DATA_ADDR_FLASH 0x70
-#define TI_RW_DATA_ADDR_DSP 0x80
-
-#define TI_RW_DATA_UNSPECIFIED 0x00
-#define TI_RW_DATA_BYTE 0x01
-#define TI_RW_DATA_WORD 0x02
-#define TI_RW_DATA_DOUBLE_WORD 0x04
-
-struct ti_write_data_bytes {
- __u8 bAddrType;
- __u8 bDataType;
- __u8 bDataCounter;
- __be16 wBaseAddrHi;
- __be16 wBaseAddrLo;
- __u8 bData[0];
-} __attribute__((packed));
-
-struct ti_read_data_request {
- __u8 bAddrType;
- __u8 bDataType;
- __u8 bDataCounter;
- __be16 wBaseAddrHi;
- __be16 wBaseAddrLo;
-} __attribute__((packed));
-
-struct ti_read_data_bytes {
- __u8 bCmdCode;
- __u8 bModuleId;
- __u8 bErrorCode;
- __u8 bData[0];
-} __attribute__((packed));
-
-/* Interrupt struct */
-struct ti_interrupt {
- __u8 bICode;
- __u8 bIInfo;
-} __attribute__((packed));
-
-/* Interrupt codes */
-#define TI_GET_PORT_FROM_CODE(c) (((c) >> 4) - 3)
-#define TI_GET_FUNC_FROM_CODE(c) ((c) & 0x0f)
-#define TI_CODE_HARDWARE_ERROR 0xFF
-#define TI_CODE_DATA_ERROR 0x03
-#define TI_CODE_MODEM_STATUS 0x04
-
-/* Download firmware max packet size */
-#define TI_DOWNLOAD_MAX_PACKET_SIZE 64
-
-/* Firmware image header */
-struct ti_firmware_header {
- __le16 wLength;
- __u8 bCheckSum;
-} __attribute__((packed));
-
-/* UART addresses */
-#define TI_UART1_BASE_ADDR 0xFFA0 /* UART 1 base address */
-#define TI_UART2_BASE_ADDR 0xFFB0 /* UART 2 base address */
-#define TI_UART_OFFSET_LCR 0x0002 /* UART MCR register offset */
-#define TI_UART_OFFSET_MCR 0x0004 /* UART MCR register offset */
-
-#endif /* _TI_3410_5052_H_ */